blob: b45e5d349c0fc43ecfe33786d2a5b03fd52eec4e [file] [log] [blame]
Andreas Huber27366fc2009-11-20 09:32:46 -08001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Glenn Kastenb0d6f102011-04-13 11:16:49 -070017#undef DEBUG_HDCP
Glenn Kasten1b11b642011-03-23 14:34:31 -070018
Andreas Huber27366fc2009-11-20 09:32:46 -080019//#define LOG_NDEBUG 0
20#define LOG_TAG "AwesomePlayer"
21#include <utils/Log.h>
22
Andreas Huber4ab5a6f2010-02-11 11:00:26 -080023#include <dlfcn.h>
24
Andreas Huber7a747b82010-06-07 15:19:40 -070025#include "include/ARTSPController.h"
Andreas Huber27366fc2009-11-20 09:32:46 -080026#include "include/AwesomePlayer.h"
Andreas Huber1314e732009-12-14 14:18:22 -080027#include "include/SoftwareRenderer.h"
Andreas Huber4d61f602010-06-10 11:17:50 -070028#include "include/NuCachedSource2.h"
29#include "include/ThrottledSource.h"
Andreas Huber54d09722010-10-12 11:34:37 -070030#include "include/MPEG2TSExtractor.h"
Gloria Wangc6091dd2011-05-03 15:59:03 -070031#include "include/TimedTextPlayer.h"
Andreas Huber27366fc2009-11-20 09:32:46 -080032
Andreas Hubera67d5382009-12-10 15:32:12 -080033#include <binder/IPCThreadState.h>
Gloria Wangd211f412011-02-19 18:37:57 -080034#include <binder/IServiceManager.h>
35#include <media/IMediaPlayerService.h>
Andreas Huber52b52cd2010-11-23 11:41:34 -080036#include <media/stagefright/foundation/hexdump.h>
37#include <media/stagefright/foundation/ADebug.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080038#include <media/stagefright/AudioPlayer.h>
39#include <media/stagefright/DataSource.h>
40#include <media/stagefright/FileSource.h>
41#include <media/stagefright/MediaBuffer.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080042#include <media/stagefright/MediaDefs.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080043#include <media/stagefright/MediaExtractor.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080044#include <media/stagefright/MediaSource.h>
45#include <media/stagefright/MetaData.h>
46#include <media/stagefright/OMXCodec.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080047
Andreas Hubere3c01832010-08-16 08:49:37 -070048#include <surfaceflinger/Surface.h>
Glenn Kastencc562a32011-02-08 17:26:17 -080049#include <gui/ISurfaceTexture.h>
50#include <gui/SurfaceTextureClient.h>
Glenn Kastenb8763f62011-01-28 12:37:51 -080051#include <surfaceflinger/ISurfaceComposer.h>
Mathias Agopian000479f2010-02-09 17:46:37 -080052
Andreas Huber7a747b82010-06-07 15:19:40 -070053#include <media/stagefright/foundation/ALooper.h>
Andreas Huberae9d5072010-12-06 10:36:06 -080054#include <media/stagefright/foundation/AMessage.h>
Andreas Huber202348e2010-06-07 14:35:29 -070055
Glenn Kasten1b11b642011-03-23 14:34:31 -070056#include <cutils/properties.h>
57
Andreas Huber6a1f5f92010-11-15 09:03:03 -080058#define USE_SURFACE_ALLOC 1
59
Andreas Huber27366fc2009-11-20 09:32:46 -080060namespace android {
61
Andreas Huber87ab9cd2010-09-03 13:20:33 -070062static int64_t kLowWaterMarkUs = 2000000ll; // 2secs
63static int64_t kHighWaterMarkUs = 10000000ll; // 10secs
Andreas Huberb2934b12011-02-08 10:18:41 -080064static int64_t kHighWaterMarkRTSPUs = 4000000ll; // 4secs
Andreas Huber96346652011-01-19 15:07:19 -080065static const size_t kLowWaterMarkBytes = 40000;
66static const size_t kHighWaterMarkBytes = 200000;
Andreas Huber87ab9cd2010-09-03 13:20:33 -070067
Andreas Huber27366fc2009-11-20 09:32:46 -080068struct AwesomeEvent : public TimedEventQueue::Event {
Andreas Huber6be780e2010-02-08 14:40:30 -080069 AwesomeEvent(
70 AwesomePlayer *player,
71 void (AwesomePlayer::*method)())
Andreas Huber27366fc2009-11-20 09:32:46 -080072 : mPlayer(player),
Andreas Huber6be780e2010-02-08 14:40:30 -080073 mMethod(method) {
Andreas Huber27366fc2009-11-20 09:32:46 -080074 }
75
76protected:
77 virtual ~AwesomeEvent() {}
78
79 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
Andreas Huber6be780e2010-02-08 14:40:30 -080080 (mPlayer->*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080081 }
82
83private:
84 AwesomePlayer *mPlayer;
Andreas Huber6be780e2010-02-08 14:40:30 -080085 void (AwesomePlayer::*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080086
87 AwesomeEvent(const AwesomeEvent &);
88 AwesomeEvent &operator=(const AwesomeEvent &);
89};
90
Andreas Huber1314e732009-12-14 14:18:22 -080091struct AwesomeLocalRenderer : public AwesomeRenderer {
92 AwesomeLocalRenderer(
Glenn Kastencc562a32011-02-08 17:26:17 -080093 const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta)
94 : mTarget(new SoftwareRenderer(nativeWindow, meta)) {
Andreas Huber1314e732009-12-14 14:18:22 -080095 }
96
97 virtual void render(MediaBuffer *buffer) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -080098 render((const uint8_t *)buffer->data() + buffer->range_offset(),
99 buffer->range_length());
100 }
101
102 void render(const void *data, size_t size) {
103 mTarget->render(data, size, NULL);
Andreas Huber1314e732009-12-14 14:18:22 -0800104 }
105
106protected:
107 virtual ~AwesomeLocalRenderer() {
108 delete mTarget;
109 mTarget = NULL;
110 }
111
112private:
Andreas Huberc23dabf2010-11-16 13:05:53 -0800113 SoftwareRenderer *mTarget;
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800114
Andreas Huber1314e732009-12-14 14:18:22 -0800115 AwesomeLocalRenderer(const AwesomeLocalRenderer &);
116 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
117};
118
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700119struct AwesomeNativeWindowRenderer : public AwesomeRenderer {
Andreas Huber940c8662010-11-16 15:26:30 -0800120 AwesomeNativeWindowRenderer(
121 const sp<ANativeWindow> &nativeWindow,
122 int32_t rotationDegrees)
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700123 : mNativeWindow(nativeWindow) {
Andreas Huber940c8662010-11-16 15:26:30 -0800124 applyRotation(rotationDegrees);
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700125 }
126
127 virtual void render(MediaBuffer *buffer) {
128 status_t err = mNativeWindow->queueBuffer(
129 mNativeWindow.get(), buffer->graphicBuffer().get());
130 if (err != 0) {
131 LOGE("queueBuffer failed with error %s (%d)", strerror(-err),
132 -err);
133 return;
134 }
135
136 sp<MetaData> metaData = buffer->meta_data();
137 metaData->setInt32(kKeyRendered, 1);
138 }
139
140protected:
141 virtual ~AwesomeNativeWindowRenderer() {}
142
143private:
144 sp<ANativeWindow> mNativeWindow;
145
Andreas Huber940c8662010-11-16 15:26:30 -0800146 void applyRotation(int32_t rotationDegrees) {
147 uint32_t transform;
148 switch (rotationDegrees) {
149 case 0: transform = 0; break;
150 case 90: transform = HAL_TRANSFORM_ROT_90; break;
151 case 180: transform = HAL_TRANSFORM_ROT_180; break;
152 case 270: transform = HAL_TRANSFORM_ROT_270; break;
153 default: transform = 0; break;
154 }
155
156 if (transform) {
157 CHECK_EQ(0, native_window_set_buffers_transform(
158 mNativeWindow.get(), transform));
159 }
160 }
161
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700162 AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &);
163 AwesomeNativeWindowRenderer &operator=(
164 const AwesomeNativeWindowRenderer &);
165};
166
Gloria Wangd211f412011-02-19 18:37:57 -0800167// To collect the decoder usage
168void addBatteryData(uint32_t params) {
169 sp<IBinder> binder =
170 defaultServiceManager()->getService(String16("media.player"));
171 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
172 CHECK(service.get() != NULL);
Andreas Huber52b52cd2010-11-23 11:41:34 -0800173
Gloria Wangd211f412011-02-19 18:37:57 -0800174 service->addBatteryData(params);
175}
176
177////////////////////////////////////////////////////////////////////////////////
Andreas Huber27366fc2009-11-20 09:32:46 -0800178AwesomePlayer::AwesomePlayer()
Andreas Huber406a18b2010-02-18 16:45:13 -0800179 : mQueueStarted(false),
180 mTimeSource(NULL),
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800181 mVideoRendererIsPreview(false),
Andreas Huber27366fc2009-11-20 09:32:46 -0800182 mAudioPlayer(NULL),
James Dong08adfd22011-01-16 11:30:13 -0800183 mDisplayWidth(0),
184 mDisplayHeight(0),
Andreas Huberffdf4782010-02-09 14:05:43 -0800185 mFlags(0),
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700186 mExtractorFlags(0),
Andreas Huberba7ec912010-02-12 10:42:02 -0800187 mVideoBuffer(NULL),
Andreas Huber3a785fe2011-03-14 10:55:40 -0700188 mDecryptHandle(NULL),
Gloria Wangc6091dd2011-05-03 15:59:03 -0700189 mLastVideoTimeUs(-1),
190 mTextPlayer(NULL) {
Andreas Huber52b52cd2010-11-23 11:41:34 -0800191 CHECK_EQ(mClient.connect(), (status_t)OK);
Andreas Huber27366fc2009-11-20 09:32:46 -0800192
193 DataSource::RegisterDefaultSniffers();
194
Andreas Huber6be780e2010-02-08 14:40:30 -0800195 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
Andreas Huber27366fc2009-11-20 09:32:46 -0800196 mVideoEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800197 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
Andreas Huber27366fc2009-11-20 09:32:46 -0800198 mStreamDoneEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800199 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
Andreas Huberb9e63832010-01-26 16:20:10 -0800200 mBufferingEventPending = false;
Andreas Huber52c78322011-01-11 15:05:28 -0800201 mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate);
202 mVideoEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800203
204 mCheckAudioStatusEvent = new AwesomeEvent(
205 this, &AwesomePlayer::onCheckAudioStatus);
206
Andreas Huber70d10c02010-02-03 11:37:29 -0800207 mAudioStatusEventPending = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800208
Andreas Huber27366fc2009-11-20 09:32:46 -0800209 reset();
210}
211
212AwesomePlayer::~AwesomePlayer() {
Andreas Huber406a18b2010-02-18 16:45:13 -0800213 if (mQueueStarted) {
214 mQueue.stop();
215 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800216
217 reset();
218
219 mClient.disconnect();
220}
221
Andreas Huberb9e63832010-01-26 16:20:10 -0800222void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800223 mQueue.cancelEvent(mVideoEvent->eventID());
224 mVideoEventPending = false;
225 mQueue.cancelEvent(mStreamDoneEvent->eventID());
226 mStreamDoneEventPending = false;
Andreas Huber70d10c02010-02-03 11:37:29 -0800227 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
228 mAudioStatusEventPending = false;
Andreas Huber52c78322011-01-11 15:05:28 -0800229 mQueue.cancelEvent(mVideoLagEvent->eventID());
230 mVideoLagEventPending = false;
Andreas Huberb9e63832010-01-26 16:20:10 -0800231
232 if (!keepBufferingGoing) {
233 mQueue.cancelEvent(mBufferingEvent->eventID());
234 mBufferingEventPending = false;
235 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800236}
237
Andreas Hubera3f43842010-01-21 10:28:45 -0800238void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800239 Mutex::Autolock autoLock(mLock);
240 mListener = listener;
241}
242
Andreas Huber433c9ac2010-01-27 16:49:05 -0800243status_t AwesomePlayer::setDataSource(
244 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800245 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800246 return setDataSource_l(uri, headers);
247}
Andreas Huber27366fc2009-11-20 09:32:46 -0800248
Andreas Huberba7ec912010-02-12 10:42:02 -0800249status_t AwesomePlayer::setDataSource_l(
250 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800251 reset_l();
252
Andreas Huberffdf4782010-02-09 14:05:43 -0800253 mUri = uri;
Andreas Huberb9e63832010-01-26 16:20:10 -0800254
Andreas Huberffdf4782010-02-09 14:05:43 -0800255 if (headers) {
256 mUriHeaders = *headers;
Andreas Huber53182c42011-02-24 14:42:48 -0800257
258 ssize_t index = mUriHeaders.indexOfKey(String8("x-hide-urls-from-log"));
259 if (index >= 0) {
260 // Browser is in "incognito" mode, suppress logging URLs.
261
262 // This isn't something that should be passed to the server.
263 mUriHeaders.removeItemsAt(index);
264
265 mFlags |= INCOGNITO;
266 }
267 }
268
269 if (!(mFlags & INCOGNITO)) {
270 LOGI("setDataSource_l('%s')", mUri.string());
271 } else {
272 LOGI("setDataSource_l(URL suppressed)");
Andreas Huberb9e63832010-01-26 16:20:10 -0800273 }
274
Andreas Huberffdf4782010-02-09 14:05:43 -0800275 // The actual work will be done during preparation in the call to
276 // ::finishSetDataSource_l to avoid blocking the calling thread in
277 // setDataSource for any significant time.
Andreas Huber27366fc2009-11-20 09:32:46 -0800278
Andreas Huberffdf4782010-02-09 14:05:43 -0800279 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800280}
281
282status_t AwesomePlayer::setDataSource(
283 int fd, int64_t offset, int64_t length) {
284 Mutex::Autolock autoLock(mLock);
285
286 reset_l();
287
Andreas Huberba7ec912010-02-12 10:42:02 -0800288 sp<DataSource> dataSource = new FileSource(fd, offset, length);
Andreas Huber27366fc2009-11-20 09:32:46 -0800289
Andreas Huberba7ec912010-02-12 10:42:02 -0800290 status_t err = dataSource->initCheck();
Andreas Huber27366fc2009-11-20 09:32:46 -0800291
292 if (err != OK) {
293 return err;
294 }
295
Andreas Huberba7ec912010-02-12 10:42:02 -0800296 mFileSource = dataSource;
297
298 return setDataSource_l(dataSource);
299}
300
Andreas Huber52b52cd2010-11-23 11:41:34 -0800301status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) {
Andreas Huberd9367262010-12-16 10:16:36 -0800302 return INVALID_OPERATION;
Andreas Huber52b52cd2010-11-23 11:41:34 -0800303}
304
Andreas Huberba7ec912010-02-12 10:42:02 -0800305status_t AwesomePlayer::setDataSource_l(
306 const sp<DataSource> &dataSource) {
307 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
Andreas Huber27366fc2009-11-20 09:32:46 -0800308
309 if (extractor == NULL) {
310 return UNKNOWN_ERROR;
311 }
312
Gloria Wangae775272011-02-24 16:40:57 -0800313 dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
Gloria Wangadc4d9c2011-02-08 13:24:08 -0800314 if (mDecryptHandle != NULL) {
315 CHECK(mDrmManagerClient);
316 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
Gloria Wangf16e1ab2011-04-29 10:44:46 -0700317 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
Gloria Wangadc4d9c2011-02-08 13:24:08 -0800318 }
Gloria Wangd5770912010-06-22 13:55:38 -0700319 }
320
Andreas Huber27366fc2009-11-20 09:32:46 -0800321 return setDataSource_l(extractor);
322}
323
324status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700325 // Attempt to approximate overall stream bitrate by summing all
326 // tracks' individual bitrates, if not all of them advertise bitrate,
327 // we have to fail.
328
329 int64_t totalBitRate = 0;
330
331 for (size_t i = 0; i < extractor->countTracks(); ++i) {
332 sp<MetaData> meta = extractor->getTrackMetaData(i);
333
334 int32_t bitrate;
335 if (!meta->findInt32(kKeyBitRate, &bitrate)) {
336 totalBitRate = -1;
337 break;
338 }
339
340 totalBitRate += bitrate;
341 }
342
343 mBitrate = totalBitRate;
344
345 LOGV("mBitrate = %lld bits/sec", mBitrate);
346
Andreas Huber27366fc2009-11-20 09:32:46 -0800347 bool haveAudio = false;
348 bool haveVideo = false;
349 for (size_t i = 0; i < extractor->countTracks(); ++i) {
350 sp<MetaData> meta = extractor->getTrackMetaData(i);
351
352 const char *mime;
353 CHECK(meta->findCString(kKeyMIMEType, &mime));
354
355 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800356 setVideoSource(extractor->getTrack(i));
357 haveVideo = true;
James Dong08adfd22011-01-16 11:30:13 -0800358
359 // Set the presentation/display size
360 int32_t displayWidth, displayHeight;
361 bool success = meta->findInt32(kKeyDisplayWidth, &displayWidth);
362 if (success) {
363 success = meta->findInt32(kKeyDisplayHeight, &displayHeight);
364 }
365 if (success) {
366 mDisplayWidth = displayWidth;
367 mDisplayHeight = displayHeight;
368 }
369
Andreas Huber27366fc2009-11-20 09:32:46 -0800370 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800371 setAudioSource(extractor->getTrack(i));
372 haveAudio = true;
Andreas Huber9fee0b22010-09-03 14:09:21 -0700373
Andreas Huber1913c1a2010-10-04 11:09:31 -0700374 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
375 // Only do this for vorbis audio, none of the other audio
376 // formats even support this ringtone specific hack and
377 // retrieving the metadata on some extractors may turn out
378 // to be very expensive.
379 sp<MetaData> fileMeta = extractor->getMetaData();
380 int32_t loop;
381 if (fileMeta != NULL
382 && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
383 mFlags |= AUTO_LOOPING;
384 }
Andreas Huber9fee0b22010-09-03 14:09:21 -0700385 }
Gloria Wangc6091dd2011-05-03 15:59:03 -0700386 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
387 addTextSource(extractor->getTrack(i));
Andreas Huber27366fc2009-11-20 09:32:46 -0800388 }
389 }
390
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700391 if (!haveAudio && !haveVideo) {
392 return UNKNOWN_ERROR;
393 }
394
395 mExtractorFlags = extractor->flags();
396
397 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800398}
399
400void AwesomePlayer::reset() {
401 Mutex::Autolock autoLock(mLock);
402 reset_l();
403}
404
405void AwesomePlayer::reset_l() {
James Dong08adfd22011-01-16 11:30:13 -0800406 mDisplayWidth = 0;
407 mDisplayHeight = 0;
Andreas Huber90c65652011-01-04 10:19:13 -0800408
Gloria Wangd5770912010-06-22 13:55:38 -0700409 if (mDecryptHandle != NULL) {
410 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
411 Playback::STOP, 0);
Gloria Wangd5770912010-06-22 13:55:38 -0700412 mDecryptHandle = NULL;
413 mDrmManagerClient = NULL;
414 }
415
Gloria Wangd211f412011-02-19 18:37:57 -0800416 if (mFlags & PLAYING) {
417 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
418 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
419 params |= IMediaPlayerService::kBatteryDataTrackAudio;
420 }
421 if (mVideoSource != NULL) {
422 params |= IMediaPlayerService::kBatteryDataTrackVideo;
423 }
424 addBatteryData(params);
425 }
426
Andreas Huberedbb4d82010-03-12 08:59:22 -0800427 if (mFlags & PREPARING) {
428 mFlags |= PREPARE_CANCELLED;
429 if (mConnectingDataSource != NULL) {
430 LOGI("interrupting the connection process");
431 mConnectingDataSource->disconnect();
Andreas Hubercb218792011-02-14 14:14:23 -0800432 } else if (mConnectingRTSPController != NULL) {
433 LOGI("interrupting the connection process");
434 mConnectingRTSPController->disconnect();
Andreas Huberedbb4d82010-03-12 08:59:22 -0800435 }
Andreas Hubereaf2c5a2010-10-19 12:18:51 -0700436
437 if (mFlags & PREPARING_CONNECTED) {
438 // We are basically done preparing, we're just buffering
439 // enough data to start playback, we can safely interrupt that.
440 finishAsyncPrepare_l();
441 }
Andreas Huberedbb4d82010-03-12 08:59:22 -0800442 }
443
Andreas Huberffdf4782010-02-09 14:05:43 -0800444 while (mFlags & PREPARING) {
445 mPreparedCondition.wait(mLock);
446 }
447
Andreas Huber27366fc2009-11-20 09:32:46 -0800448 cancelPlayerEvents();
449
Andreas Huber4d61f602010-06-10 11:17:50 -0700450 mCachedSource.clear();
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800451 mAudioTrack.clear();
452 mVideoTrack.clear();
453
Andreas Huberba7ec912010-02-12 10:42:02 -0800454 // Shutdown audio first, so that the respone to the reset request
455 // appears to happen instantaneously as far as the user is concerned
456 // If we did this later, audio would continue playing while we
457 // shutdown the video-related resources and the player appear to
458 // not be as responsive to a reset request.
Andreas Huberedbb4d82010-03-12 08:59:22 -0800459 if (mAudioPlayer == NULL && mAudioSource != NULL) {
460 // If we had an audio player, it would have effectively
461 // taken possession of the audio source and stopped it when
462 // _it_ is stopped. Otherwise this is still our responsibility.
463 mAudioSource->stop();
464 }
Andreas Huberba7ec912010-02-12 10:42:02 -0800465 mAudioSource.clear();
466
Andreas Huberba7ec912010-02-12 10:42:02 -0800467 mTimeSource = NULL;
468
469 delete mAudioPlayer;
470 mAudioPlayer = NULL;
471
Gloria Wangc6091dd2011-05-03 15:59:03 -0700472 if (mTextPlayer != NULL) {
473 delete mTextPlayer;
474 mTextPlayer = NULL;
475 }
476
Andreas Huber3522b5a52010-01-22 14:36:53 -0800477 mVideoRenderer.clear();
478
Andreas Hubere0dd7d32010-08-24 14:33:58 -0700479 if (mRTSPController != NULL) {
480 mRTSPController->disconnect();
481 mRTSPController.clear();
482 }
483
Andreas Huber27366fc2009-11-20 09:32:46 -0800484 if (mVideoSource != NULL) {
Andreas Huber3a785fe2011-03-14 10:55:40 -0700485 shutdownVideoDecoder_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800486 }
487
Andreas Huber27366fc2009-11-20 09:32:46 -0800488 mDurationUs = -1;
489 mFlags = 0;
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700490 mExtractorFlags = 0;
Andreas Huber27366fc2009-11-20 09:32:46 -0800491 mTimeSourceDeltaUs = 0;
492 mVideoTimeUs = 0;
493
Andreas Hubera2c29972011-02-24 12:05:40 -0800494 mSeeking = NO_SEEK;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700495 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800496 mSeekTimeUs = 0;
Andreas Huberb9e63832010-01-26 16:20:10 -0800497
Andreas Huberffdf4782010-02-09 14:05:43 -0800498 mUri.setTo("");
499 mUriHeaders.clear();
Andreas Huberba7ec912010-02-12 10:42:02 -0800500
501 mFileSource.clear();
502
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700503 mBitrate = -1;
Andreas Huber3a785fe2011-03-14 10:55:40 -0700504 mLastVideoTimeUs = -1;
Andreas Huber27366fc2009-11-20 09:32:46 -0800505}
506
Andreas Huber6be780e2010-02-08 14:40:30 -0800507void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
Andreas Hubera3f43842010-01-21 10:28:45 -0800508 if (mListener != NULL) {
509 sp<MediaPlayerBase> listener = mListener.promote();
510
511 if (listener != NULL) {
Andreas Huber6be780e2010-02-08 14:40:30 -0800512 listener->sendEvent(msg, ext1, ext2);
Andreas Hubera3f43842010-01-21 10:28:45 -0800513 }
514 }
515}
516
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700517bool AwesomePlayer::getBitrate(int64_t *bitrate) {
James Dongb1262a82010-11-16 14:04:54 -0800518 off64_t size;
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700519 if (mDurationUs >= 0 && mCachedSource != NULL
520 && mCachedSource->getSize(&size) == OK) {
521 *bitrate = size * 8000000ll / mDurationUs; // in bits/sec
522 return true;
523 }
524
525 if (mBitrate >= 0) {
526 *bitrate = mBitrate;
527 return true;
528 }
529
530 *bitrate = 0;
531
532 return false;
533}
534
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700535// Returns true iff cached duration is available/applicable.
536bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700537 int64_t bitrate;
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700538
539 if (mRTSPController != NULL) {
540 *durationUs = mRTSPController->getQueueDurationUs(eos);
541 return true;
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700542 } else if (mCachedSource != NULL && getBitrate(&bitrate)) {
Bryan Mawhinneye26275b2011-01-18 19:12:21 +0000543 status_t finalStatus;
544 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700545 *durationUs = cachedDataRemaining * 8000000ll / bitrate;
Bryan Mawhinneye26275b2011-01-18 19:12:21 +0000546 *eos = (finalStatus != OK);
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700547 return true;
548 }
549
550 return false;
551}
552
Andreas Huber10b920c2010-11-11 15:37:17 -0800553void AwesomePlayer::ensureCacheIsFetching_l() {
554 if (mCachedSource != NULL) {
555 mCachedSource->resumeFetchingIfNecessary();
556 }
557}
558
Andreas Huber52c78322011-01-11 15:05:28 -0800559void AwesomePlayer::onVideoLagUpdate() {
560 Mutex::Autolock autoLock(mLock);
561 if (!mVideoLagEventPending) {
562 return;
563 }
564 mVideoLagEventPending = false;
565
566 int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs();
567 int64_t videoLateByUs = audioTimeUs - mVideoTimeUs;
568
Andreas Huber16ede3c2011-03-25 13:03:14 -0700569 if (!(mFlags & VIDEO_AT_EOS) && videoLateByUs > 300000ll) {
Andreas Huber52c78322011-01-11 15:05:28 -0800570 LOGV("video late by %lld ms.", videoLateByUs / 1000ll);
571
572 notifyListener_l(
573 MEDIA_INFO,
574 MEDIA_INFO_VIDEO_TRACK_LAGGING,
575 videoLateByUs / 1000ll);
576 }
577
578 postVideoLagEvent_l();
579}
580
Andreas Huberb9e63832010-01-26 16:20:10 -0800581void AwesomePlayer::onBufferingUpdate() {
582 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800583 if (!mBufferingEventPending) {
584 return;
585 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800586 mBufferingEventPending = false;
587
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700588 if (mCachedSource != NULL) {
Bryan Mawhinneye26275b2011-01-18 19:12:21 +0000589 status_t finalStatus;
590 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
591 bool eos = (finalStatus != OK);
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700592
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700593 if (eos) {
Bryan Mawhinneye26275b2011-01-18 19:12:21 +0000594 if (finalStatus == ERROR_END_OF_STREAM) {
595 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
596 }
Andreas Huber05f67872010-10-04 11:36:39 -0700597 if (mFlags & PREPARING) {
598 LOGV("cache has reached EOS, prepare is done.");
599 finishAsyncPrepare_l();
600 }
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700601 } else {
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700602 int64_t bitrate;
603 if (getBitrate(&bitrate)) {
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700604 size_t cachedSize = mCachedSource->cachedSize();
605 int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
606
607 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
608 if (percentage > 100) {
609 percentage = 100;
610 }
611
612 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
613 } else {
614 // We don't know the bitrate of the stream, use absolute size
615 // limits to maintain the cache.
616
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700617 if ((mFlags & PLAYING) && !eos
618 && (cachedDataRemaining < kLowWaterMarkBytes)) {
619 LOGI("cache is running low (< %d) , pausing.",
620 kLowWaterMarkBytes);
621 mFlags |= CACHE_UNDERRUN;
622 pause_l();
Andreas Huber10b920c2010-11-11 15:37:17 -0800623 ensureCacheIsFetching_l();
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700624 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
625 } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
626 if (mFlags & CACHE_UNDERRUN) {
627 LOGI("cache has filled up (> %d), resuming.",
628 kHighWaterMarkBytes);
629 mFlags &= ~CACHE_UNDERRUN;
630 play_l();
631 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
632 } else if (mFlags & PREPARING) {
633 LOGV("cache has filled up (> %d), prepare is done",
634 kHighWaterMarkBytes);
635 finishAsyncPrepare_l();
636 }
637 }
638 }
639 }
640 }
641
642 int64_t cachedDurationUs;
643 bool eos;
644 if (getCachedDuration_l(&cachedDurationUs, &eos)) {
Andreas Huber10b920c2010-11-11 15:37:17 -0800645 LOGV("cachedDurationUs = %.2f secs, eos=%d",
646 cachedDurationUs / 1E6, eos);
647
Andreas Huberb2934b12011-02-08 10:18:41 -0800648 int64_t highWaterMarkUs =
649 (mRTSPController != NULL) ? kHighWaterMarkRTSPUs : kHighWaterMarkUs;
650
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700651 if ((mFlags & PLAYING) && !eos
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700652 && (cachedDurationUs < kLowWaterMarkUs)) {
653 LOGI("cache is running low (%.2f secs) , pausing.",
654 cachedDurationUs / 1E6);
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700655 mFlags |= CACHE_UNDERRUN;
656 pause_l();
Andreas Huber10b920c2010-11-11 15:37:17 -0800657 ensureCacheIsFetching_l();
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700658 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
Andreas Huberb2934b12011-02-08 10:18:41 -0800659 } else if (eos || cachedDurationUs > highWaterMarkUs) {
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700660 if (mFlags & CACHE_UNDERRUN) {
661 LOGI("cache has filled up (%.2f secs), resuming.",
662 cachedDurationUs / 1E6);
663 mFlags &= ~CACHE_UNDERRUN;
664 play_l();
665 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
666 } else if (mFlags & PREPARING) {
667 LOGV("cache has filled up (%.2f secs), prepare is done",
668 cachedDurationUs / 1E6);
669 finishAsyncPrepare_l();
Andreas Huberc23296e2010-08-25 12:31:48 -0700670 }
Andreas Huberc23296e2010-08-25 12:31:48 -0700671 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800672 }
Andreas Huber4d61f602010-06-10 11:17:50 -0700673
Andreas Huber4d61f602010-06-10 11:17:50 -0700674 postBufferingEvent_l();
Andreas Huberb9e63832010-01-26 16:20:10 -0800675}
676
Andreas Huber27366fc2009-11-20 09:32:46 -0800677void AwesomePlayer::onStreamDone() {
678 // Posted whenever any stream finishes playing.
679
680 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800681 if (!mStreamDoneEventPending) {
682 return;
683 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800684 mStreamDoneEventPending = false;
685
Andreas Huberd6c421f2011-02-16 09:05:38 -0800686 if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
Andreas Huber971305d2010-07-07 13:35:27 -0700687 LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
688
689 notifyListener_l(
690 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
691
Andreas Huberc743f452010-10-05 10:25:34 -0700692 pause_l(true /* at eos */);
Andreas Huber971305d2010-07-07 13:35:27 -0700693
694 mFlags |= AT_EOS;
695 return;
696 }
697
698 const bool allDone =
699 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
700 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
701
702 if (!allDone) {
703 return;
704 }
705
Andreas Huber9fee0b22010-09-03 14:09:21 -0700706 if (mFlags & (LOOPING | AUTO_LOOPING)) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800707 seekTo_l(0);
708
Andreas Huber7085b6842010-02-03 16:02:02 -0800709 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800710 postVideoEvent_l();
711 }
712 } else {
Andreas Huber971305d2010-07-07 13:35:27 -0700713 LOGV("MEDIA_PLAYBACK_COMPLETE");
714 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800715
Andreas Huberc743f452010-10-05 10:25:34 -0700716 pause_l(true /* at eos */);
Andreas Huber406a18b2010-02-18 16:45:13 -0800717
718 mFlags |= AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800719 }
720}
721
722status_t AwesomePlayer::play() {
723 Mutex::Autolock autoLock(mLock);
Andreas Huber4d61f602010-06-10 11:17:50 -0700724
725 mFlags &= ~CACHE_UNDERRUN;
726
Andreas Huberba7ec912010-02-12 10:42:02 -0800727 return play_l();
728}
Andreas Huber27366fc2009-11-20 09:32:46 -0800729
Andreas Huberba7ec912010-02-12 10:42:02 -0800730status_t AwesomePlayer::play_l() {
Andreas Huber0a84f4f2011-02-07 11:43:12 -0800731 mFlags &= ~SEEK_PREVIEW;
732
Andreas Huber27366fc2009-11-20 09:32:46 -0800733 if (mFlags & PLAYING) {
734 return OK;
735 }
736
Andreas Huberffdf4782010-02-09 14:05:43 -0800737 if (!(mFlags & PREPARED)) {
738 status_t err = prepare_l();
739
740 if (err != OK) {
741 return err;
742 }
743 }
744
Andreas Huber27366fc2009-11-20 09:32:46 -0800745 mFlags |= PLAYING;
746 mFlags |= FIRST_FRAME;
747
Gloria Wang95dbffb2010-11-04 17:38:39 -0700748 if (mDecryptHandle != NULL) {
749 int64_t position;
750 getPosition(&position);
751 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
752 Playback::START, position / 1000);
753 }
754
Andreas Huber27366fc2009-11-20 09:32:46 -0800755 if (mAudioSource != NULL) {
756 if (mAudioPlayer == NULL) {
757 if (mAudioSink != NULL) {
Andreas Huber2b359ed2010-09-28 11:56:39 -0700758 mAudioPlayer = new AudioPlayer(mAudioSink, this);
Andreas Huber27366fc2009-11-20 09:32:46 -0800759 mAudioPlayer->setSource(mAudioSource);
Andreas Huberdc9927d2010-03-08 15:46:13 -0800760
Andreas Huber27366fc2009-11-20 09:32:46 -0800761 mTimeSource = mAudioPlayer;
762
Andreas Huber498422f2011-03-16 10:41:25 -0700763 // If there was a seek request before we ever started,
764 // honor the request now.
765 // Make sure to do this before starting the audio player
766 // to avoid a race condition.
767 seekAudioIfNecessary_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800768 }
Andreas Huberce8a1012011-02-11 13:09:36 -0800769 }
770
771 CHECK(!(mFlags & AUDIO_RUNNING));
772
773 if (mVideoSource == NULL) {
774 status_t err = startAudioPlayer_l();
775
776 if (err != OK) {
777 delete mAudioPlayer;
778 mAudioPlayer = NULL;
779
780 mFlags &= ~(PLAYING | FIRST_FRAME);
781
782 if (mDecryptHandle != NULL) {
783 mDrmManagerClient->setPlaybackStatus(
784 mDecryptHandle, Playback::STOP, 0);
785 }
786
787 return err;
788 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800789 }
790 }
791
792 if (mTimeSource == NULL && mAudioPlayer == NULL) {
Andreas Huber971305d2010-07-07 13:35:27 -0700793 mTimeSource = &mSystemTimeSource;
Andreas Huber27366fc2009-11-20 09:32:46 -0800794 }
795
796 if (mVideoSource != NULL) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800797 // Kick off video playback
798 postVideoEvent_l();
Andreas Huber52c78322011-01-11 15:05:28 -0800799
800 if (mAudioSource != NULL && mVideoSource != NULL) {
801 postVideoLagEvent_l();
802 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800803 }
804
Andreas Huber406a18b2010-02-18 16:45:13 -0800805 if (mFlags & AT_EOS) {
806 // Legacy behaviour, if a stream finishes playing and then
807 // is started again, we play from the start...
808 seekTo_l(0);
809 }
810
Gloria Wangd211f412011-02-19 18:37:57 -0800811 uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted
812 | IMediaPlayerService::kBatteryDataTrackDecoder;
813 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
814 params |= IMediaPlayerService::kBatteryDataTrackAudio;
815 }
816 if (mVideoSource != NULL) {
817 params |= IMediaPlayerService::kBatteryDataTrackVideo;
818 }
819 addBatteryData(params);
820
Andreas Huber27366fc2009-11-20 09:32:46 -0800821 return OK;
822}
823
Andreas Huberce8a1012011-02-11 13:09:36 -0800824status_t AwesomePlayer::startAudioPlayer_l() {
825 CHECK(!(mFlags & AUDIO_RUNNING));
826
827 if (mAudioSource == NULL || mAudioPlayer == NULL) {
828 return OK;
829 }
830
831 if (!(mFlags & AUDIOPLAYER_STARTED)) {
832 mFlags |= AUDIOPLAYER_STARTED;
833
Andreas Huber5fd43e32011-05-10 13:56:39 -0700834 bool wasSeeking = mAudioPlayer->isSeeking();
835
Andreas Huberce8a1012011-02-11 13:09:36 -0800836 // We've already started the MediaSource in order to enable
837 // the prefetcher to read its data.
838 status_t err = mAudioPlayer->start(
839 true /* sourceAlreadyStarted */);
840
841 if (err != OK) {
842 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
843 return err;
844 }
Andreas Huber5fd43e32011-05-10 13:56:39 -0700845
846 if (wasSeeking) {
847 CHECK(!mAudioPlayer->isSeeking());
848
849 // We will have finished the seek while starting the audio player.
850 postAudioSeekComplete_l();
851 }
Andreas Huberce8a1012011-02-11 13:09:36 -0800852 } else {
853 mAudioPlayer->resume();
854 }
855
856 mFlags |= AUDIO_RUNNING;
857
858 mWatchForAudioEOS = true;
859
860 return OK;
861}
862
Andreas Hubere3c01832010-08-16 08:49:37 -0700863void AwesomePlayer::notifyVideoSize_l() {
864 sp<MetaData> meta = mVideoSource->getFormat();
865
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800866 int32_t cropLeft, cropTop, cropRight, cropBottom;
867 if (!meta->findRect(
868 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
869 int32_t width, height;
870 CHECK(meta->findInt32(kKeyWidth, &width));
871 CHECK(meta->findInt32(kKeyHeight, &height));
872
873 cropLeft = cropTop = 0;
874 cropRight = width - 1;
875 cropBottom = height - 1;
876
877 LOGV("got dimensions only %d x %d", width, height);
878 } else {
879 LOGV("got crop rect %d, %d, %d, %d",
880 cropLeft, cropTop, cropRight, cropBottom);
881 }
882
James Dong7e91d912011-03-18 12:19:43 -0700883 int32_t displayWidth;
884 if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
885 LOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
886 mDisplayWidth = displayWidth;
887 }
888 int32_t displayHeight;
889 if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
890 LOGV("Display height changed (%d=>%d)", mDisplayHeight, displayHeight);
891 mDisplayHeight = displayHeight;
892 }
893
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800894 int32_t usableWidth = cropRight - cropLeft + 1;
895 int32_t usableHeight = cropBottom - cropTop + 1;
James Dong08adfd22011-01-16 11:30:13 -0800896 if (mDisplayWidth != 0) {
897 usableWidth = mDisplayWidth;
898 }
899 if (mDisplayHeight != 0) {
900 usableHeight = mDisplayHeight;
901 }
Andreas Hubere3c01832010-08-16 08:49:37 -0700902
Andreas Huber940c8662010-11-16 15:26:30 -0800903 int32_t rotationDegrees;
904 if (!mVideoTrack->getFormat()->findInt32(
905 kKeyRotation, &rotationDegrees)) {
906 rotationDegrees = 0;
907 }
908
909 if (rotationDegrees == 90 || rotationDegrees == 270) {
910 notifyListener_l(
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800911 MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
Andreas Huber940c8662010-11-16 15:26:30 -0800912 } else {
913 notifyListener_l(
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800914 MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
Andreas Huber940c8662010-11-16 15:26:30 -0800915 }
Andreas Hubere3c01832010-08-16 08:49:37 -0700916}
917
Andreas Huber27366fc2009-11-20 09:32:46 -0800918void AwesomePlayer::initRenderer_l() {
Glenn Kastencc562a32011-02-08 17:26:17 -0800919 if (mNativeWindow == NULL) {
Andreas Huberc23dabf2010-11-16 13:05:53 -0800920 return;
921 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800922
Andreas Huberc23dabf2010-11-16 13:05:53 -0800923 sp<MetaData> meta = mVideoSource->getFormat();
Andreas Huber27366fc2009-11-20 09:32:46 -0800924
Andreas Huberc23dabf2010-11-16 13:05:53 -0800925 int32_t format;
926 const char *component;
927 int32_t decodedWidth, decodedHeight;
928 CHECK(meta->findInt32(kKeyColorFormat, &format));
929 CHECK(meta->findCString(kKeyDecoderComponent, &component));
930 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
931 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
Andreas Hubera67d5382009-12-10 15:32:12 -0800932
Andreas Huber940c8662010-11-16 15:26:30 -0800933 int32_t rotationDegrees;
934 if (!mVideoTrack->getFormat()->findInt32(
935 kKeyRotation, &rotationDegrees)) {
936 rotationDegrees = 0;
937 }
938
Andreas Huberc23dabf2010-11-16 13:05:53 -0800939 mVideoRenderer.clear();
Andreas Hubera67d5382009-12-10 15:32:12 -0800940
Andreas Huberc23dabf2010-11-16 13:05:53 -0800941 // Must ensure that mVideoRenderer's destructor is actually executed
942 // before creating a new one.
943 IPCThreadState::self()->flushCommands();
944
Andreas Huber4b3913a2011-05-11 14:13:42 -0700945 if (USE_SURFACE_ALLOC
946 && !strncmp(component, "OMX.", 4)
947 && strncmp(component, "OMX.google.", 11)) {
Andreas Huberc23dabf2010-11-16 13:05:53 -0800948 // Hardware decoders avoid the CPU color conversion by decoding
949 // directly to ANativeBuffers, so we must use a renderer that
950 // just pushes those buffers to the ANativeWindow.
Andreas Huber940c8662010-11-16 15:26:30 -0800951 mVideoRenderer =
Glenn Kastencc562a32011-02-08 17:26:17 -0800952 new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees);
Andreas Huberc23dabf2010-11-16 13:05:53 -0800953 } else {
954 // Other decoders are instantiated locally and as a consequence
955 // allocate their buffers in local address space. This renderer
956 // then performs a color conversion and copy to get the data
957 // into the ANativeBuffer.
Glenn Kastencc562a32011-02-08 17:26:17 -0800958 mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta);
Andreas Huber27366fc2009-11-20 09:32:46 -0800959 }
960}
961
962status_t AwesomePlayer::pause() {
963 Mutex::Autolock autoLock(mLock);
Andreas Huber4d61f602010-06-10 11:17:50 -0700964
965 mFlags &= ~CACHE_UNDERRUN;
966
Andreas Huber27366fc2009-11-20 09:32:46 -0800967 return pause_l();
968}
969
Andreas Huberc743f452010-10-05 10:25:34 -0700970status_t AwesomePlayer::pause_l(bool at_eos) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800971 if (!(mFlags & PLAYING)) {
972 return OK;
973 }
974
Andreas Huberb9e63832010-01-26 16:20:10 -0800975 cancelPlayerEvents(true /* keepBufferingGoing */);
Andreas Huber27366fc2009-11-20 09:32:46 -0800976
Andreas Huberce8a1012011-02-11 13:09:36 -0800977 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Andreas Huberc743f452010-10-05 10:25:34 -0700978 if (at_eos) {
979 // If we played the audio stream to completion we
980 // want to make sure that all samples remaining in the audio
981 // track's queue are played out.
982 mAudioPlayer->pause(true /* playPendingSamples */);
983 } else {
984 mAudioPlayer->pause();
985 }
Andreas Huberce8a1012011-02-11 13:09:36 -0800986
987 mFlags &= ~AUDIO_RUNNING;
Andreas Huber27366fc2009-11-20 09:32:46 -0800988 }
989
Gloria Wangc6091dd2011-05-03 15:59:03 -0700990 if (mFlags & TEXTPLAYER_STARTED) {
991 mTextPlayer->pause();
992 mFlags &= ~TEXT_RUNNING;
993 }
994
Andreas Huber27366fc2009-11-20 09:32:46 -0800995 mFlags &= ~PLAYING;
996
Gloria Wangd5770912010-06-22 13:55:38 -0700997 if (mDecryptHandle != NULL) {
998 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
999 Playback::PAUSE, 0);
1000 }
1001
Gloria Wangd211f412011-02-19 18:37:57 -08001002 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
1003 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
1004 params |= IMediaPlayerService::kBatteryDataTrackAudio;
1005 }
1006 if (mVideoSource != NULL) {
1007 params |= IMediaPlayerService::kBatteryDataTrackVideo;
1008 }
1009
1010 addBatteryData(params);
1011
Andreas Huber27366fc2009-11-20 09:32:46 -08001012 return OK;
1013}
1014
1015bool AwesomePlayer::isPlaying() const {
Andreas Huber4d61f602010-06-10 11:17:50 -07001016 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
Andreas Huber27366fc2009-11-20 09:32:46 -08001017}
1018
Andreas Hubere3c01832010-08-16 08:49:37 -07001019void AwesomePlayer::setSurface(const sp<Surface> &surface) {
1020 Mutex::Autolock autoLock(mLock);
1021
1022 mSurface = surface;
Andreas Huber3a785fe2011-03-14 10:55:40 -07001023 setNativeWindow_l(surface);
Glenn Kastencc562a32011-02-08 17:26:17 -08001024}
1025
1026void AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
1027 Mutex::Autolock autoLock(mLock);
1028
1029 mSurface.clear();
1030 if (surfaceTexture != NULL) {
Andreas Huber3a785fe2011-03-14 10:55:40 -07001031 setNativeWindow_l(new SurfaceTextureClient(surfaceTexture));
1032 }
1033}
1034
1035void AwesomePlayer::shutdownVideoDecoder_l() {
1036 if (mVideoBuffer) {
1037 mVideoBuffer->release();
1038 mVideoBuffer = NULL;
Glenn Kastencc562a32011-02-08 17:26:17 -08001039 }
1040
Andreas Huber3a785fe2011-03-14 10:55:40 -07001041 mVideoSource->stop();
1042
1043 // The following hack is necessary to ensure that the OMX
1044 // component is completely released by the time we may try
1045 // to instantiate it again.
1046 wp<MediaSource> tmp = mVideoSource;
1047 mVideoSource.clear();
1048 while (tmp.promote() != NULL) {
1049 usleep(1000);
1050 }
1051 IPCThreadState::self()->flushCommands();
1052}
1053
1054void AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
1055 mNativeWindow = native;
1056
1057 if (mVideoSource == NULL) {
1058 return;
1059 }
1060
1061 LOGI("attempting to reconfigure to use new surface");
1062
1063 bool wasPlaying = (mFlags & PLAYING) != 0;
1064
1065 pause_l();
1066 mVideoRenderer.clear();
1067
1068 shutdownVideoDecoder_l();
1069
1070 CHECK_EQ(initVideoDecoder(), (status_t)OK);
1071
1072 if (mLastVideoTimeUs >= 0) {
1073 mSeeking = SEEK;
1074 mSeekNotificationSent = true;
1075 mSeekTimeUs = mLastVideoTimeUs;
1076 mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
1077 }
1078
1079 if (wasPlaying) {
1080 play_l();
1081 }
Andreas Hubere3c01832010-08-16 08:49:37 -07001082}
1083
Andreas Huber27366fc2009-11-20 09:32:46 -08001084void AwesomePlayer::setAudioSink(
1085 const sp<MediaPlayerBase::AudioSink> &audioSink) {
1086 Mutex::Autolock autoLock(mLock);
1087
1088 mAudioSink = audioSink;
1089}
1090
1091status_t AwesomePlayer::setLooping(bool shouldLoop) {
1092 Mutex::Autolock autoLock(mLock);
1093
1094 mFlags = mFlags & ~LOOPING;
1095
1096 if (shouldLoop) {
1097 mFlags |= LOOPING;
1098 }
1099
1100 return OK;
1101}
1102
1103status_t AwesomePlayer::getDuration(int64_t *durationUs) {
Andreas Huber252573c2010-03-26 10:17:17 -07001104 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001105
1106 if (mDurationUs < 0) {
1107 return UNKNOWN_ERROR;
1108 }
1109
1110 *durationUs = mDurationUs;
1111
1112 return OK;
1113}
1114
1115status_t AwesomePlayer::getPosition(int64_t *positionUs) {
Andreas Hubereeb97d92010-08-27 13:29:08 -07001116 if (mRTSPController != NULL) {
1117 *positionUs = mRTSPController->getNormalPlayTimeUs();
1118 }
Andreas Hubera2c29972011-02-24 12:05:40 -08001119 else if (mSeeking != NO_SEEK) {
Andreas Huberddb709c2010-04-07 10:24:35 -07001120 *positionUs = mSeekTimeUs;
Andreas Huber16ede3c2011-03-25 13:03:14 -07001121 } else if (mVideoSource != NULL
1122 && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) {
Andreas Huber252573c2010-03-26 10:17:17 -07001123 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001124 *positionUs = mVideoTimeUs;
1125 } else if (mAudioPlayer != NULL) {
1126 *positionUs = mAudioPlayer->getMediaTimeUs();
1127 } else {
1128 *positionUs = 0;
1129 }
1130
1131 return OK;
1132}
1133
1134status_t AwesomePlayer::seekTo(int64_t timeUs) {
Andreas Huber10b9b3f2010-10-08 10:16:24 -07001135 if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
Andreas Huber62f7ffe2010-05-06 10:18:05 -07001136 Mutex::Autolock autoLock(mLock);
1137 return seekTo_l(timeUs);
1138 }
1139
1140 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -08001141}
1142
Gloria Wangc6091dd2011-05-03 15:59:03 -07001143status_t AwesomePlayer::setTimedTextTrackIndex(int32_t index) {
1144 if (mTextPlayer != NULL) {
1145 if (index >= 0) { // to turn on a text track
1146 status_t err = mTextPlayer->setTimedTextTrackIndex(index);
1147 if (err != OK) {
1148 return err;
1149 }
1150
1151 mFlags |= TEXT_RUNNING;
1152 mFlags |= TEXTPLAYER_STARTED;
1153 return OK;
1154 } else { // to turn off the text track display
1155 if (mFlags & TEXT_RUNNING) {
1156 mFlags &= ~TEXT_RUNNING;
1157 }
1158 if (mFlags & TEXTPLAYER_STARTED) {
1159 mFlags &= ~TEXTPLAYER_STARTED;
1160 }
1161
1162 return mTextPlayer->setTimedTextTrackIndex(index);
1163 }
1164 } else {
1165 return INVALID_OPERATION;
1166 }
1167}
1168
Andreas Huber0c46b692010-10-08 15:21:08 -07001169// static
1170void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) {
1171 static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone();
1172}
1173
1174void AwesomePlayer::onRTSPSeekDone() {
1175 notifyListener_l(MEDIA_SEEK_COMPLETE);
1176 mSeekNotificationSent = true;
1177}
1178
Andreas Huber27366fc2009-11-20 09:32:46 -08001179status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
Andreas Hubere0dd7d32010-08-24 14:33:58 -07001180 if (mRTSPController != NULL) {
Andreas Huber0c46b692010-10-08 15:21:08 -07001181 mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this);
Andreas Hubere0dd7d32010-08-24 14:33:58 -07001182 return OK;
1183 }
1184
Andreas Huber4d61f602010-06-10 11:17:50 -07001185 if (mFlags & CACHE_UNDERRUN) {
1186 mFlags &= ~CACHE_UNDERRUN;
1187 play_l();
1188 }
1189
Andreas Huber16ede3c2011-03-25 13:03:14 -07001190 if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) {
1191 // Video playback completed before, there's no pending
1192 // video event right now. In order for this new seek
1193 // to be honored, we need to post one.
1194
1195 postVideoEvent_l();
1196 }
1197
Andreas Hubera2c29972011-02-24 12:05:40 -08001198 mSeeking = SEEK;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001199 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -08001200 mSeekTimeUs = timeUs;
Andreas Huber971305d2010-07-07 13:35:27 -07001201 mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
Andreas Huber27366fc2009-11-20 09:32:46 -08001202
1203 seekAudioIfNecessary_l();
1204
Gloria Wangc6091dd2011-05-03 15:59:03 -07001205 if (mFlags & TEXTPLAYER_STARTED) {
1206 mTextPlayer->seekTo(mSeekTimeUs);
1207 }
1208
Andreas Huber8e2b9412010-03-31 09:40:15 -07001209 if (!(mFlags & PLAYING)) {
1210 LOGV("seeking while paused, sending SEEK_COMPLETE notification"
1211 " immediately.");
1212
1213 notifyListener_l(MEDIA_SEEK_COMPLETE);
1214 mSeekNotificationSent = true;
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001215
1216 if ((mFlags & PREPARED) && mVideoSource != NULL) {
1217 mFlags |= SEEK_PREVIEW;
1218 postVideoEvent_l();
1219 }
Andreas Huber8e2b9412010-03-31 09:40:15 -07001220 }
1221
Andreas Huber27366fc2009-11-20 09:32:46 -08001222 return OK;
1223}
1224
1225void AwesomePlayer::seekAudioIfNecessary_l() {
Andreas Hubera2c29972011-02-24 12:05:40 -08001226 if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001227 mAudioPlayer->seekTo(mSeekTimeUs);
1228
Andreas Huber70d10c02010-02-03 11:37:29 -08001229 mWatchForAudioSeekComplete = true;
1230 mWatchForAudioEOS = true;
Gloria Wangd5770912010-06-22 13:55:38 -07001231
1232 if (mDecryptHandle != NULL) {
1233 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1234 Playback::PAUSE, 0);
1235 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1236 Playback::START, mSeekTimeUs / 1000);
1237 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001238 }
1239}
1240
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001241void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
1242 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001243
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001244 mAudioTrack = source;
1245}
1246
Gloria Wangc6091dd2011-05-03 15:59:03 -07001247void AwesomePlayer::addTextSource(sp<MediaSource> source) {
1248 CHECK(source != NULL);
1249
1250 if (mTextPlayer == NULL) {
1251 mTextPlayer = new TimedTextPlayer(this, mListener, &mQueue);
1252 }
1253
1254 mTextPlayer->addTextSource(source);
1255}
1256
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001257status_t AwesomePlayer::initAudioDecoder() {
1258 sp<MetaData> meta = mAudioTrack->getFormat();
Andreas Huberc79827a2010-01-05 10:54:55 -08001259
1260 const char *mime;
1261 CHECK(meta->findCString(kKeyMIMEType, &mime));
1262
1263 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001264 mAudioSource = mAudioTrack;
Andreas Huberc79827a2010-01-05 10:54:55 -08001265 } else {
1266 mAudioSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001267 mClient.interface(), mAudioTrack->getFormat(),
Andreas Huberc79827a2010-01-05 10:54:55 -08001268 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001269 mAudioTrack);
Andreas Huberc79827a2010-01-05 10:54:55 -08001270 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001271
1272 if (mAudioSource != NULL) {
1273 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001274 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -07001275 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001276 if (mDurationUs < 0 || durationUs > mDurationUs) {
1277 mDurationUs = durationUs;
1278 }
1279 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001280
Andreas Huber3c78a1b2010-05-13 09:15:21 -07001281 status_t err = mAudioSource->start();
1282
1283 if (err != OK) {
1284 mAudioSource.clear();
1285 return err;
1286 }
Andreas Huberd0332ad2010-04-12 16:05:57 -07001287 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
1288 // For legacy reasons we're simply going to ignore the absence
1289 // of an audio decoder for QCELP instead of aborting playback
1290 // altogether.
1291 return OK;
1292 }
Andreas Huberdc9927d2010-03-08 15:46:13 -08001293
Andreas Huber27366fc2009-11-20 09:32:46 -08001294 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
1295}
1296
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001297void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
1298 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001299
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001300 mVideoTrack = source;
1301}
1302
Andreas Huber4c19bf92010-09-08 14:32:20 -07001303status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
Glenn Kastenb8763f62011-01-28 12:37:51 -08001304
1305 // Either the application or the DRM system can independently say
1306 // that there must be a hardware-protected path to an external video sink.
1307 // For now we always require a hardware-protected path to external video sink
1308 // if content is DRMed, but eventually this could be optional per DRM agent.
1309 // When the application wants protection, then
1310 // (USE_SURFACE_ALLOC && (mSurface != 0) &&
1311 // (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp))
1312 // will be true, but that part is already handled by SurfaceFlinger.
Glenn Kasten1b11b642011-03-23 14:34:31 -07001313
1314#ifdef DEBUG_HDCP
1315 // For debugging, we allow a system property to control the protected usage.
1316 // In case of uninitialized or unexpected property, we default to "DRM only".
1317 bool setProtectionBit = false;
1318 char value[PROPERTY_VALUE_MAX];
1319 if (property_get("persist.sys.hdcp_checking", value, NULL)) {
1320 if (!strcmp(value, "never")) {
1321 // nop
1322 } else if (!strcmp(value, "always")) {
1323 setProtectionBit = true;
1324 } else if (!strcmp(value, "drm-only")) {
1325 if (mDecryptHandle != NULL) {
1326 setProtectionBit = true;
1327 }
1328 // property value is empty, or unexpected value
1329 } else {
1330 if (mDecryptHandle != NULL) {
1331 setProtectionBit = true;
1332 }
1333 }
1334 // can' read property value
1335 } else {
1336 if (mDecryptHandle != NULL) {
1337 setProtectionBit = true;
1338 }
1339 }
1340 // note that usage bit is already cleared, so no need to clear it in the "else" case
1341 if (setProtectionBit) {
1342 flags |= OMXCodec::kEnableGrallocUsageProtected;
1343 }
1344#else
Glenn Kastenb8763f62011-01-28 12:37:51 -08001345 if (mDecryptHandle != NULL) {
1346 flags |= OMXCodec::kEnableGrallocUsageProtected;
1347 }
Glenn Kasten1b11b642011-03-23 14:34:31 -07001348#endif
Glenn Kastenb8763f62011-01-28 12:37:51 -08001349 LOGV("initVideoDecoder flags=0x%x", flags);
Andreas Huber27366fc2009-11-20 09:32:46 -08001350 mVideoSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001351 mClient.interface(), mVideoTrack->getFormat(),
Andreas Huber27366fc2009-11-20 09:32:46 -08001352 false, // createEncoder
Andreas Huber57648e42010-08-04 10:14:30 -07001353 mVideoTrack,
Glenn Kastencc562a32011-02-08 17:26:17 -08001354 NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001355
1356 if (mVideoSource != NULL) {
1357 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001358 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -07001359 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001360 if (mDurationUs < 0 || durationUs > mDurationUs) {
1361 mDurationUs = durationUs;
1362 }
1363 }
1364
Andreas Huber1919e5a2010-05-20 10:37:06 -07001365 status_t err = mVideoSource->start();
1366
1367 if (err != OK) {
1368 mVideoSource.clear();
1369 return err;
1370 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001371 }
1372
1373 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
1374}
1375
Andreas Huber4d450a82010-10-19 09:34:44 -07001376void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
Andreas Hubera2c29972011-02-24 12:05:40 -08001377 if (mSeeking == SEEK_VIDEO_ONLY) {
1378 mSeeking = NO_SEEK;
1379 return;
1380 }
1381
1382 if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
Andreas Huber4d450a82010-10-19 09:34:44 -07001383 return;
1384 }
1385
1386 if (mAudioPlayer != NULL) {
Jamie Gennis6913c612010-10-20 15:55:43 -07001387 LOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
Andreas Huber4d450a82010-10-19 09:34:44 -07001388
1389 // If we don't have a video time, seek audio to the originally
1390 // requested seek time instead.
1391
1392 mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
Andreas Huber4d450a82010-10-19 09:34:44 -07001393 mWatchForAudioSeekComplete = true;
Andreas Huber16ede3c2011-03-25 13:03:14 -07001394 mWatchForAudioEOS = true;
Andreas Huber4d450a82010-10-19 09:34:44 -07001395 } else if (!mSeekNotificationSent) {
1396 // If we're playing video only, report seek complete now,
1397 // otherwise audio player will notify us later.
1398 notifyListener_l(MEDIA_SEEK_COMPLETE);
Andreas Huberf8a5b552011-03-16 15:42:45 -07001399 mSeekNotificationSent = true;
Andreas Huber4d450a82010-10-19 09:34:44 -07001400 }
1401
1402 mFlags |= FIRST_FRAME;
Andreas Hubera2c29972011-02-24 12:05:40 -08001403 mSeeking = NO_SEEK;
Gloria Wang3f9a8192010-10-29 14:50:17 -07001404
1405 if (mDecryptHandle != NULL) {
1406 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1407 Playback::PAUSE, 0);
1408 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1409 Playback::START, videoTimeUs / 1000);
1410 }
Andreas Huber4d450a82010-10-19 09:34:44 -07001411}
1412
Andreas Huber6be780e2010-02-08 14:40:30 -08001413void AwesomePlayer::onVideoEvent() {
Andreas Huber27366fc2009-11-20 09:32:46 -08001414 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -08001415 if (!mVideoEventPending) {
1416 // The event has been cancelled in reset_l() but had already
1417 // been scheduled for execution at that time.
1418 return;
1419 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001420 mVideoEventPending = false;
1421
Andreas Hubera2c29972011-02-24 12:05:40 -08001422 if (mSeeking != NO_SEEK) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001423 if (mVideoBuffer) {
1424 mVideoBuffer->release();
1425 mVideoBuffer = NULL;
1426 }
Andreas Huber4d61f602010-06-10 11:17:50 -07001427
Andreas Hubera2c29972011-02-24 12:05:40 -08001428 if (mSeeking == SEEK && mCachedSource != NULL && mAudioSource != NULL
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001429 && !(mFlags & SEEK_PREVIEW)) {
Andreas Huber4d61f602010-06-10 11:17:50 -07001430 // We're going to seek the video source first, followed by
1431 // the audio source.
1432 // In order to avoid jumps in the DataSource offset caused by
1433 // the audio codec prefetching data from the old locations
1434 // while the video codec is already reading data from the new
1435 // locations, we'll "pause" the audio source, causing it to
1436 // stop reading input data until a subsequent seek.
1437
Andreas Huberce8a1012011-02-11 13:09:36 -08001438 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Andreas Huber4d61f602010-06-10 11:17:50 -07001439 mAudioPlayer->pause();
Andreas Huberce8a1012011-02-11 13:09:36 -08001440
1441 mFlags &= ~AUDIO_RUNNING;
Andreas Huber4d61f602010-06-10 11:17:50 -07001442 }
1443 mAudioSource->pause();
1444 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001445 }
1446
1447 if (!mVideoBuffer) {
1448 MediaSource::ReadOptions options;
Andreas Hubera2c29972011-02-24 12:05:40 -08001449 if (mSeeking != NO_SEEK) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001450 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
1451
Andreas Huber6624c9f2010-07-20 15:04:28 -07001452 options.setSeekTo(
Andreas Hubera2c29972011-02-24 12:05:40 -08001453 mSeekTimeUs,
1454 mSeeking == SEEK_VIDEO_ONLY
1455 ? MediaSource::ReadOptions::SEEK_NEXT_SYNC
1456 : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
Andreas Huber27366fc2009-11-20 09:32:46 -08001457 }
1458 for (;;) {
1459 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberb1f5ee42009-12-14 15:34:11 -08001460 options.clearSeekTo();
Andreas Huber27366fc2009-11-20 09:32:46 -08001461
1462 if (err != OK) {
Andreas Huber52b52cd2010-11-23 11:41:34 -08001463 CHECK(mVideoBuffer == NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001464
1465 if (err == INFO_FORMAT_CHANGED) {
1466 LOGV("VideoSource signalled format change.");
1467
Andreas Hubere3c01832010-08-16 08:49:37 -07001468 notifyVideoSize_l();
1469
Andreas Huber7085b6842010-02-03 16:02:02 -08001470 if (mVideoRenderer != NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001471 mVideoRendererIsPreview = false;
Andreas Huber7085b6842010-02-03 16:02:02 -08001472 initRenderer_l();
1473 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001474 continue;
1475 }
1476
Andreas Huber4d450a82010-10-19 09:34:44 -07001477 // So video playback is complete, but we may still have
1478 // a seek request pending that needs to be applied
1479 // to the audio track.
Andreas Hubera2c29972011-02-24 12:05:40 -08001480 if (mSeeking != NO_SEEK) {
Andreas Huber4d450a82010-10-19 09:34:44 -07001481 LOGV("video stream ended while seeking!");
1482 }
1483 finishSeekIfNecessary(-1);
1484
Andreas Huber16ede3c2011-03-25 13:03:14 -07001485 if (mAudioPlayer != NULL
1486 && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1487 startAudioPlayer_l();
1488 }
1489
Andreas Huber971305d2010-07-07 13:35:27 -07001490 mFlags |= VIDEO_AT_EOS;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001491 postStreamDoneEvent_l(err);
Andreas Huber27366fc2009-11-20 09:32:46 -08001492 return;
1493 }
1494
Andreas Hubera67d5382009-12-10 15:32:12 -08001495 if (mVideoBuffer->range_length() == 0) {
Andreas Huber6ddcf012009-12-10 15:32:12 -08001496 // Some decoders, notably the PV AVC software decoder
1497 // return spurious empty buffers that we just want to ignore.
1498
Andreas Hubera67d5382009-12-10 15:32:12 -08001499 mVideoBuffer->release();
1500 mVideoBuffer = NULL;
1501 continue;
1502 }
1503
Andreas Huber27366fc2009-11-20 09:32:46 -08001504 break;
1505 }
1506 }
1507
1508 int64_t timeUs;
1509 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1510
Andreas Huber3a785fe2011-03-14 10:55:40 -07001511 mLastVideoTimeUs = timeUs;
1512
Andreas Hubera2c29972011-02-24 12:05:40 -08001513 if (mSeeking == SEEK_VIDEO_ONLY) {
1514 if (mSeekTimeUs > timeUs) {
1515 LOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us",
1516 mSeekTimeUs, timeUs);
1517 }
1518 }
1519
Andreas Huber252573c2010-03-26 10:17:17 -07001520 {
1521 Mutex::Autolock autoLock(mMiscStateLock);
1522 mVideoTimeUs = timeUs;
1523 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001524
Andreas Hubera2c29972011-02-24 12:05:40 -08001525 SeekType wasSeeking = mSeeking;
Andreas Huber4d450a82010-10-19 09:34:44 -07001526 finishSeekIfNecessary(timeUs);
Andreas Huber27366fc2009-11-20 09:32:46 -08001527
Andreas Huberce8a1012011-02-11 13:09:36 -08001528 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1529 status_t err = startAudioPlayer_l();
1530 if (err != OK) {
1531 LOGE("Startung the audio player failed w/ err %d", err);
1532 return;
1533 }
1534 }
1535
Gloria Wangc6091dd2011-05-03 15:59:03 -07001536 if ((mFlags & TEXTPLAYER_STARTED) && !(mFlags & (TEXT_RUNNING | SEEK_PREVIEW))) {
1537 mTextPlayer->resume();
1538 mFlags |= TEXT_RUNNING;
1539 }
1540
Andreas Huber971305d2010-07-07 13:35:27 -07001541 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
1542
Andreas Huber27366fc2009-11-20 09:32:46 -08001543 if (mFlags & FIRST_FRAME) {
1544 mFlags &= ~FIRST_FRAME;
Andreas Huber971305d2010-07-07 13:35:27 -07001545 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
Andreas Huber27366fc2009-11-20 09:32:46 -08001546 }
1547
1548 int64_t realTimeUs, mediaTimeUs;
Andreas Huber971305d2010-07-07 13:35:27 -07001549 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
Andreas Huber27366fc2009-11-20 09:32:46 -08001550 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1551 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1552 }
1553
Andreas Hubera2c29972011-02-24 12:05:40 -08001554 if (wasSeeking == SEEK_VIDEO_ONLY) {
1555 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1556
1557 int64_t latenessUs = nowUs - timeUs;
1558
1559 if (latenessUs > 0) {
1560 LOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6);
1561 }
1562 }
1563
1564 if (wasSeeking == NO_SEEK) {
Andreas Huber614d22c2010-10-29 15:47:52 -07001565 // Let's display the first frame after seeking right away.
Andreas Huberf88f8442010-08-10 11:18:36 -07001566
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001567 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
Andreas Huber27366fc2009-11-20 09:32:46 -08001568
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001569 int64_t latenessUs = nowUs - timeUs;
1570
Andreas Hubera2c29972011-02-24 12:05:40 -08001571 if (latenessUs > 500000ll
1572 && mRTSPController == NULL
1573 && mAudioPlayer != NULL
1574 && mAudioPlayer->getMediaTimeMapping(
1575 &realTimeUs, &mediaTimeUs)) {
1576 LOGI("we're much too late (%.2f secs), video skipping ahead",
1577 latenessUs / 1E6);
1578
1579 mVideoBuffer->release();
1580 mVideoBuffer = NULL;
1581
1582 mSeeking = SEEK_VIDEO_ONLY;
1583 mSeekTimeUs = mediaTimeUs;
1584
1585 postVideoEvent_l();
1586 return;
1587 }
1588
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001589 if (latenessUs > 40000) {
1590 // We're more than 40ms late.
Andreas Huber2334d822011-04-01 13:27:42 -07001591 LOGV("we're late by %lld us (%.2f secs), dropping frame",
1592 latenessUs, latenessUs / 1E6);
1593 mVideoBuffer->release();
1594 mVideoBuffer = NULL;
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001595
Andreas Huber2334d822011-04-01 13:27:42 -07001596 postVideoEvent_l();
1597 return;
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001598 }
1599
1600 if (latenessUs < -10000) {
1601 // We're more than 10ms early.
1602
1603 postVideoEvent_l(10000);
pmehendale28f939d2011-01-06 14:43:49 -08001604 return;
1605 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001606 }
1607
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001608 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
1609 mVideoRendererIsPreview = false;
1610
Andreas Huber7085b6842010-02-03 16:02:02 -08001611 initRenderer_l();
1612 }
1613
1614 if (mVideoRenderer != NULL) {
1615 mVideoRenderer->render(mVideoBuffer);
1616 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001617
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001618 mVideoBuffer->release();
Andreas Huber27366fc2009-11-20 09:32:46 -08001619 mVideoBuffer = NULL;
1620
Andreas Hubera2c29972011-02-24 12:05:40 -08001621 if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) {
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001622 mFlags &= ~SEEK_PREVIEW;
1623 return;
1624 }
1625
Andreas Huber27366fc2009-11-20 09:32:46 -08001626 postVideoEvent_l();
1627}
1628
1629void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
1630 if (mVideoEventPending) {
1631 return;
1632 }
1633
1634 mVideoEventPending = true;
1635 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1636}
1637
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001638void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001639 if (mStreamDoneEventPending) {
1640 return;
1641 }
1642 mStreamDoneEventPending = true;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001643
1644 mStreamDoneStatus = status;
Andreas Huber27366fc2009-11-20 09:32:46 -08001645 mQueue.postEvent(mStreamDoneEvent);
1646}
1647
Andreas Huberb9e63832010-01-26 16:20:10 -08001648void AwesomePlayer::postBufferingEvent_l() {
Andreas Huberb9e63832010-01-26 16:20:10 -08001649 if (mBufferingEventPending) {
1650 return;
1651 }
1652 mBufferingEventPending = true;
1653 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1654}
1655
Andreas Huber52c78322011-01-11 15:05:28 -08001656void AwesomePlayer::postVideoLagEvent_l() {
1657 if (mVideoLagEventPending) {
1658 return;
1659 }
1660 mVideoLagEventPending = true;
1661 mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
1662}
1663
Andreas Huber4dc482d2011-03-22 10:31:21 -07001664void AwesomePlayer::postCheckAudioStatusEvent_l(int64_t delayUs) {
Andreas Huber70d10c02010-02-03 11:37:29 -08001665 if (mAudioStatusEventPending) {
1666 return;
1667 }
1668 mAudioStatusEventPending = true;
Andreas Huber4dc482d2011-03-22 10:31:21 -07001669 mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
Andreas Huber70d10c02010-02-03 11:37:29 -08001670}
1671
1672void AwesomePlayer::onCheckAudioStatus() {
1673 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -08001674 if (!mAudioStatusEventPending) {
1675 // Event was dispatched and while we were blocking on the mutex,
1676 // has already been cancelled.
1677 return;
1678 }
1679
Andreas Huber70d10c02010-02-03 11:37:29 -08001680 mAudioStatusEventPending = false;
1681
1682 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1683 mWatchForAudioSeekComplete = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001684
1685 if (!mSeekNotificationSent) {
1686 notifyListener_l(MEDIA_SEEK_COMPLETE);
1687 mSeekNotificationSent = true;
1688 }
Andreas Huberddb709c2010-04-07 10:24:35 -07001689
Andreas Hubera2c29972011-02-24 12:05:40 -08001690 mSeeking = NO_SEEK;
Andreas Huber70d10c02010-02-03 11:37:29 -08001691 }
1692
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001693 status_t finalStatus;
1694 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
Andreas Huber70d10c02010-02-03 11:37:29 -08001695 mWatchForAudioEOS = false;
Andreas Huber971305d2010-07-07 13:35:27 -07001696 mFlags |= AUDIO_AT_EOS;
1697 mFlags |= FIRST_FRAME;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001698 postStreamDoneEvent_l(finalStatus);
Andreas Huber70d10c02010-02-03 11:37:29 -08001699 }
Andreas Huber70d10c02010-02-03 11:37:29 -08001700}
1701
Andreas Huber6be780e2010-02-08 14:40:30 -08001702status_t AwesomePlayer::prepare() {
1703 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001704 return prepare_l();
1705}
Andreas Huber6be780e2010-02-08 14:40:30 -08001706
Andreas Huberffdf4782010-02-09 14:05:43 -08001707status_t AwesomePlayer::prepare_l() {
1708 if (mFlags & PREPARED) {
1709 return OK;
1710 }
1711
1712 if (mFlags & PREPARING) {
1713 return UNKNOWN_ERROR;
1714 }
1715
1716 mIsAsyncPrepare = false;
Andreas Huber6be780e2010-02-08 14:40:30 -08001717 status_t err = prepareAsync_l();
1718
1719 if (err != OK) {
1720 return err;
1721 }
1722
Andreas Huberffdf4782010-02-09 14:05:43 -08001723 while (mFlags & PREPARING) {
Andreas Huber6be780e2010-02-08 14:40:30 -08001724 mPreparedCondition.wait(mLock);
1725 }
1726
Andreas Huberffdf4782010-02-09 14:05:43 -08001727 return mPrepareResult;
Andreas Huber6be780e2010-02-08 14:40:30 -08001728}
1729
1730status_t AwesomePlayer::prepareAsync() {
1731 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001732
1733 if (mFlags & PREPARING) {
1734 return UNKNOWN_ERROR; // async prepare already pending
1735 }
1736
1737 mIsAsyncPrepare = true;
Andreas Huber6be780e2010-02-08 14:40:30 -08001738 return prepareAsync_l();
1739}
1740
1741status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001742 if (mFlags & PREPARING) {
1743 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huber6be780e2010-02-08 14:40:30 -08001744 }
1745
Andreas Huber406a18b2010-02-18 16:45:13 -08001746 if (!mQueueStarted) {
1747 mQueue.start();
1748 mQueueStarted = true;
1749 }
1750
Andreas Huberffdf4782010-02-09 14:05:43 -08001751 mFlags |= PREPARING;
Andreas Huber6be780e2010-02-08 14:40:30 -08001752 mAsyncPrepareEvent = new AwesomeEvent(
1753 this, &AwesomePlayer::onPrepareAsyncEvent);
1754
1755 mQueue.postEvent(mAsyncPrepareEvent);
1756
1757 return OK;
1758}
1759
Andreas Huberffdf4782010-02-09 14:05:43 -08001760status_t AwesomePlayer::finishSetDataSource_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001761 sp<DataSource> dataSource;
1762
Andreas Huber118a1502011-02-17 13:35:08 -08001763 if (!strncasecmp("http://", mUri.string(), 7)
1764 || !strncasecmp("https://", mUri.string(), 8)) {
Andreas Huber5f5719e2011-03-08 15:59:28 -08001765 mConnectingDataSource = HTTPBase::Create(
1766 (mFlags & INCOGNITO)
1767 ? HTTPBase::kFlagIncognito
1768 : 0);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001769
1770 mLock.unlock();
Andreas Huber3a53dc52010-06-11 09:57:46 -07001771 status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001772 mLock.lock();
1773
1774 if (err != OK) {
1775 mConnectingDataSource.clear();
1776
1777 LOGI("mConnectingDataSource->connect() returned %d", err);
1778 return err;
1779 }
1780
Andreas Huber4d61f602010-06-10 11:17:50 -07001781#if 0
1782 mCachedSource = new NuCachedSource2(
1783 new ThrottledSource(
1784 mConnectingDataSource, 50 * 1024 /* bytes/sec */));
1785#else
1786 mCachedSource = new NuCachedSource2(mConnectingDataSource);
1787#endif
Andreas Huberedbb4d82010-03-12 08:59:22 -08001788 mConnectingDataSource.clear();
Andreas Huber4d61f602010-06-10 11:17:50 -07001789
1790 dataSource = mCachedSource;
Andreas Huber96346652011-01-19 15:07:19 -08001791
Andreas Hubera2e57ca2011-03-30 11:15:27 -07001792 String8 contentType = dataSource->getMIMEType();
Andreas Huber96346652011-01-19 15:07:19 -08001793
Andreas Hubera2e57ca2011-03-30 11:15:27 -07001794 if (strncasecmp(contentType.string(), "audio/", 6)) {
1795 // We're not doing this for streams that appear to be audio-only
1796 // streams to ensure that even low bandwidth streams start
1797 // playing back fairly instantly.
Andreas Huber96346652011-01-19 15:07:19 -08001798
Andreas Hubera2e57ca2011-03-30 11:15:27 -07001799 // We're going to prefill the cache before trying to instantiate
1800 // the extractor below, as the latter is an operation that otherwise
1801 // could block on the datasource for a significant amount of time.
1802 // During that time we'd be unable to abort the preparation phase
1803 // without this prefill.
Andreas Huber96346652011-01-19 15:07:19 -08001804
Andreas Hubera2e57ca2011-03-30 11:15:27 -07001805 mLock.unlock();
1806
1807 for (;;) {
1808 status_t finalStatus;
1809 size_t cachedDataRemaining =
1810 mCachedSource->approxDataRemaining(&finalStatus);
1811
1812 if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
1813 || (mFlags & PREPARE_CANCELLED)) {
1814 break;
1815 }
1816
1817 usleep(200000);
Andreas Huber96346652011-01-19 15:07:19 -08001818 }
1819
Andreas Hubera2e57ca2011-03-30 11:15:27 -07001820 mLock.lock();
Andreas Huber96346652011-01-19 15:07:19 -08001821 }
1822
Andreas Huber96346652011-01-19 15:07:19 -08001823 if (mFlags & PREPARE_CANCELLED) {
1824 LOGI("Prepare cancelled while waiting for initial cache fill.");
1825 return UNKNOWN_ERROR;
1826 }
Andreas Huber7a747b82010-06-07 15:19:40 -07001827 } else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
1828 if (mLooper == NULL) {
1829 mLooper = new ALooper;
Andreas Huberc4e0b702010-08-27 15:21:07 -07001830 mLooper->setName("rtsp");
Andreas Huber7a747b82010-06-07 15:19:40 -07001831 mLooper->start();
1832 }
1833 mRTSPController = new ARTSPController(mLooper);
Andreas Hubercb218792011-02-14 14:14:23 -08001834 mConnectingRTSPController = mRTSPController;
1835
1836 mLock.unlock();
Andreas Huber7a747b82010-06-07 15:19:40 -07001837 status_t err = mRTSPController->connect(mUri.string());
Andreas Hubercb218792011-02-14 14:14:23 -08001838 mLock.lock();
1839
1840 mConnectingRTSPController.clear();
Andreas Huber202348e2010-06-07 14:35:29 -07001841
Andreas Huber7a747b82010-06-07 15:19:40 -07001842 LOGI("ARTSPController::connect returned %d", err);
1843
1844 if (err != OK) {
1845 mRTSPController.clear();
1846 return err;
1847 }
1848
1849 sp<MediaExtractor> extractor = mRTSPController.get();
Andreas Huber202348e2010-06-07 14:35:29 -07001850 return setDataSource_l(extractor);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001851 } else {
1852 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1853 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001854
1855 if (dataSource == NULL) {
1856 return UNKNOWN_ERROR;
1857 }
1858
1859 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1860
1861 if (extractor == NULL) {
1862 return UNKNOWN_ERROR;
1863 }
1864
Gloria Wangae775272011-02-24 16:40:57 -08001865 dataSource->getDrmInfo(mDecryptHandle, &mDrmManagerClient);
1866
Gloria Wangc2c22e72010-11-01 15:53:16 -07001867 if (mDecryptHandle != NULL) {
Gloria Wangadc4d9c2011-02-08 13:24:08 -08001868 CHECK(mDrmManagerClient);
James Dong3be15932011-03-25 08:41:57 -07001869 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
Gloria Wangf16e1ab2011-04-29 10:44:46 -07001870 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
Gloria Wangc2c22e72010-11-01 15:53:16 -07001871 }
Gloria Wangd5770912010-06-22 13:55:38 -07001872 }
1873
Andreas Huberffdf4782010-02-09 14:05:43 -08001874 return setDataSource_l(extractor);
1875}
1876
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001877void AwesomePlayer::abortPrepare(status_t err) {
1878 CHECK(err != OK);
1879
1880 if (mIsAsyncPrepare) {
1881 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1882 }
1883
1884 mPrepareResult = err;
Andreas Hubereaf2c5a2010-10-19 12:18:51 -07001885 mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001886 mAsyncPrepareEvent = NULL;
1887 mPreparedCondition.broadcast();
1888}
1889
Andreas Huberf71daba2010-03-24 09:24:40 -07001890// static
1891bool AwesomePlayer::ContinuePreparation(void *cookie) {
1892 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
1893
1894 return (me->mFlags & PREPARE_CANCELLED) == 0;
1895}
1896
Andreas Huber6be780e2010-02-08 14:40:30 -08001897void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001898 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001899
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001900 if (mFlags & PREPARE_CANCELLED) {
1901 LOGI("prepare was cancelled before doing anything");
1902 abortPrepare(UNKNOWN_ERROR);
1903 return;
1904 }
1905
1906 if (mUri.size() > 0) {
1907 status_t err = finishSetDataSource_l();
1908
1909 if (err != OK) {
1910 abortPrepare(err);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001911 return;
1912 }
Andreas Huber6be780e2010-02-08 14:40:30 -08001913 }
1914
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001915 if (mVideoTrack != NULL && mVideoSource == NULL) {
1916 status_t err = initVideoDecoder();
Andreas Huber6be780e2010-02-08 14:40:30 -08001917
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001918 if (err != OK) {
1919 abortPrepare(err);
1920 return;
1921 }
1922 }
1923
1924 if (mAudioTrack != NULL && mAudioSource == NULL) {
1925 status_t err = initAudioDecoder();
1926
1927 if (err != OK) {
1928 abortPrepare(err);
1929 return;
1930 }
1931 }
1932
Andreas Hubereaf2c5a2010-10-19 12:18:51 -07001933 mFlags |= PREPARING_CONNECTED;
1934
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001935 if (mCachedSource != NULL || mRTSPController != NULL) {
1936 postBufferingEvent_l();
1937 } else {
1938 finishAsyncPrepare_l();
1939 }
1940}
1941
1942void AwesomePlayer::finishAsyncPrepare_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001943 if (mIsAsyncPrepare) {
Andreas Hubere3c01832010-08-16 08:49:37 -07001944 if (mVideoSource == NULL) {
Andreas Huberffdf4782010-02-09 14:05:43 -08001945 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1946 } else {
Andreas Hubere3c01832010-08-16 08:49:37 -07001947 notifyVideoSize_l();
Andreas Huberffdf4782010-02-09 14:05:43 -08001948 }
1949
1950 notifyListener_l(MEDIA_PREPARED);
Andreas Huber6be780e2010-02-08 14:40:30 -08001951 }
1952
Andreas Huberffdf4782010-02-09 14:05:43 -08001953 mPrepareResult = OK;
Andreas Hubereaf2c5a2010-10-19 12:18:51 -07001954 mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
Andreas Huberffdf4782010-02-09 14:05:43 -08001955 mFlags |= PREPARED;
Andreas Huber6be780e2010-02-08 14:40:30 -08001956 mAsyncPrepareEvent = NULL;
Andreas Huberffdf4782010-02-09 14:05:43 -08001957 mPreparedCondition.broadcast();
Andreas Huber6be780e2010-02-08 14:40:30 -08001958}
1959
Andreas Huber62f7ffe2010-05-06 10:18:05 -07001960uint32_t AwesomePlayer::flags() const {
1961 return mExtractorFlags;
1962}
1963
Andreas Huber4dc482d2011-03-22 10:31:21 -07001964void AwesomePlayer::postAudioEOS(int64_t delayUs) {
Andreas Huber8e64c312011-04-04 09:12:56 -07001965 Mutex::Autolock autoLock(mLock);
Andreas Huber4dc482d2011-03-22 10:31:21 -07001966 postCheckAudioStatusEvent_l(delayUs);
Andreas Huber2b359ed2010-09-28 11:56:39 -07001967}
1968
1969void AwesomePlayer::postAudioSeekComplete() {
Andreas Huber8e64c312011-04-04 09:12:56 -07001970 Mutex::Autolock autoLock(mLock);
Andreas Huber5fd43e32011-05-10 13:56:39 -07001971 postAudioSeekComplete_l();
1972}
1973
1974void AwesomePlayer::postAudioSeekComplete_l() {
Andreas Huber4dc482d2011-03-22 10:31:21 -07001975 postCheckAudioStatusEvent_l(0 /* delayUs */);
Andreas Huber2b359ed2010-09-28 11:56:39 -07001976}
1977
Gloria Wangd01ec6e2011-04-25 17:28:22 -07001978status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
Gloria Wangc6091dd2011-05-03 15:59:03 -07001979 if (key == KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX) {
1980 return setTimedTextTrackIndex(request.readInt32());
1981 }
1982 return ERROR_UNSUPPORTED;
Gloria Wangd01ec6e2011-04-25 17:28:22 -07001983}
1984
1985status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
1986 return OK;
1987}
Andreas Huber27366fc2009-11-20 09:32:46 -08001988} // namespace android