blob: 027a1ce95be061f91ed1c7a19eca94fa8514a9d6 [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"
Andreas Huber27366fc2009-11-20 09:32:46 -080031
Andreas Hubera67d5382009-12-10 15:32:12 -080032#include <binder/IPCThreadState.h>
Gloria Wangd211f412011-02-19 18:37:57 -080033#include <binder/IServiceManager.h>
34#include <media/IMediaPlayerService.h>
Andreas Huber52b52cd2010-11-23 11:41:34 -080035#include <media/stagefright/foundation/hexdump.h>
36#include <media/stagefright/foundation/ADebug.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080037#include <media/stagefright/AudioPlayer.h>
38#include <media/stagefright/DataSource.h>
39#include <media/stagefright/FileSource.h>
40#include <media/stagefright/MediaBuffer.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080041#include <media/stagefright/MediaDefs.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080042#include <media/stagefright/MediaExtractor.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080043#include <media/stagefright/MediaSource.h>
44#include <media/stagefright/MetaData.h>
45#include <media/stagefright/OMXCodec.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080046
Andreas Hubere3c01832010-08-16 08:49:37 -070047#include <surfaceflinger/Surface.h>
Glenn Kastencc562a32011-02-08 17:26:17 -080048#include <gui/ISurfaceTexture.h>
49#include <gui/SurfaceTextureClient.h>
Glenn Kastenb8763f62011-01-28 12:37:51 -080050#include <surfaceflinger/ISurfaceComposer.h>
Mathias Agopian000479f2010-02-09 17:46:37 -080051
Andreas Huber7a747b82010-06-07 15:19:40 -070052#include <media/stagefright/foundation/ALooper.h>
Andreas Huberae9d5072010-12-06 10:36:06 -080053#include <media/stagefright/foundation/AMessage.h>
Andreas Huber202348e2010-06-07 14:35:29 -070054
Glenn Kasten1b11b642011-03-23 14:34:31 -070055#include <cutils/properties.h>
56
Andreas Huber6a1f5f92010-11-15 09:03:03 -080057#define USE_SURFACE_ALLOC 1
Andreas Hubera2c29972011-02-24 12:05:40 -080058#define FRAME_DROP_FREQ 0
Andreas Huber6a1f5f92010-11-15 09:03:03 -080059
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),
Gloria Wangd5770912010-06-22 13:55:38 -0700188 mDecryptHandle(NULL) {
Andreas Huber52b52cd2010-11-23 11:41:34 -0800189 CHECK_EQ(mClient.connect(), (status_t)OK);
Andreas Huber27366fc2009-11-20 09:32:46 -0800190
191 DataSource::RegisterDefaultSniffers();
192
Andreas Huber6be780e2010-02-08 14:40:30 -0800193 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
Andreas Huber27366fc2009-11-20 09:32:46 -0800194 mVideoEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800195 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
Andreas Huber27366fc2009-11-20 09:32:46 -0800196 mStreamDoneEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800197 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
Andreas Huberb9e63832010-01-26 16:20:10 -0800198 mBufferingEventPending = false;
Andreas Huber52c78322011-01-11 15:05:28 -0800199 mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate);
200 mVideoEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800201
202 mCheckAudioStatusEvent = new AwesomeEvent(
203 this, &AwesomePlayer::onCheckAudioStatus);
204
Andreas Huber70d10c02010-02-03 11:37:29 -0800205 mAudioStatusEventPending = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800206
Andreas Huber27366fc2009-11-20 09:32:46 -0800207 reset();
208}
209
210AwesomePlayer::~AwesomePlayer() {
Andreas Huber406a18b2010-02-18 16:45:13 -0800211 if (mQueueStarted) {
212 mQueue.stop();
213 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800214
215 reset();
216
217 mClient.disconnect();
218}
219
Andreas Huberb9e63832010-01-26 16:20:10 -0800220void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800221 mQueue.cancelEvent(mVideoEvent->eventID());
222 mVideoEventPending = false;
223 mQueue.cancelEvent(mStreamDoneEvent->eventID());
224 mStreamDoneEventPending = false;
Andreas Huber70d10c02010-02-03 11:37:29 -0800225 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
226 mAudioStatusEventPending = false;
Andreas Huber52c78322011-01-11 15:05:28 -0800227 mQueue.cancelEvent(mVideoLagEvent->eventID());
228 mVideoLagEventPending = false;
Andreas Huberb9e63832010-01-26 16:20:10 -0800229
230 if (!keepBufferingGoing) {
231 mQueue.cancelEvent(mBufferingEvent->eventID());
232 mBufferingEventPending = false;
233 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800234}
235
Andreas Hubera3f43842010-01-21 10:28:45 -0800236void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800237 Mutex::Autolock autoLock(mLock);
238 mListener = listener;
239}
240
Andreas Huber433c9ac2010-01-27 16:49:05 -0800241status_t AwesomePlayer::setDataSource(
242 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800243 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800244 return setDataSource_l(uri, headers);
245}
Andreas Huber27366fc2009-11-20 09:32:46 -0800246
Andreas Huberba7ec912010-02-12 10:42:02 -0800247status_t AwesomePlayer::setDataSource_l(
248 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800249 reset_l();
250
Andreas Huberffdf4782010-02-09 14:05:43 -0800251 mUri = uri;
Andreas Huberb9e63832010-01-26 16:20:10 -0800252
Andreas Huberffdf4782010-02-09 14:05:43 -0800253 if (headers) {
254 mUriHeaders = *headers;
Andreas Huber53182c42011-02-24 14:42:48 -0800255
256 ssize_t index = mUriHeaders.indexOfKey(String8("x-hide-urls-from-log"));
257 if (index >= 0) {
258 // Browser is in "incognito" mode, suppress logging URLs.
259
260 // This isn't something that should be passed to the server.
261 mUriHeaders.removeItemsAt(index);
262
263 mFlags |= INCOGNITO;
264 }
265 }
266
267 if (!(mFlags & INCOGNITO)) {
268 LOGI("setDataSource_l('%s')", mUri.string());
269 } else {
270 LOGI("setDataSource_l(URL suppressed)");
Andreas Huberb9e63832010-01-26 16:20:10 -0800271 }
272
Andreas Huberffdf4782010-02-09 14:05:43 -0800273 // The actual work will be done during preparation in the call to
274 // ::finishSetDataSource_l to avoid blocking the calling thread in
275 // setDataSource for any significant time.
Andreas Huber27366fc2009-11-20 09:32:46 -0800276
Andreas Huberffdf4782010-02-09 14:05:43 -0800277 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800278}
279
280status_t AwesomePlayer::setDataSource(
281 int fd, int64_t offset, int64_t length) {
282 Mutex::Autolock autoLock(mLock);
283
284 reset_l();
285
Andreas Huberba7ec912010-02-12 10:42:02 -0800286 sp<DataSource> dataSource = new FileSource(fd, offset, length);
Andreas Huber27366fc2009-11-20 09:32:46 -0800287
Andreas Huberba7ec912010-02-12 10:42:02 -0800288 status_t err = dataSource->initCheck();
Andreas Huber27366fc2009-11-20 09:32:46 -0800289
290 if (err != OK) {
291 return err;
292 }
293
Andreas Huberba7ec912010-02-12 10:42:02 -0800294 mFileSource = dataSource;
295
296 return setDataSource_l(dataSource);
297}
298
Andreas Huber52b52cd2010-11-23 11:41:34 -0800299status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) {
Andreas Huberd9367262010-12-16 10:16:36 -0800300 return INVALID_OPERATION;
Andreas Huber52b52cd2010-11-23 11:41:34 -0800301}
302
Andreas Huberba7ec912010-02-12 10:42:02 -0800303status_t AwesomePlayer::setDataSource_l(
304 const sp<DataSource> &dataSource) {
305 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
Andreas Huber27366fc2009-11-20 09:32:46 -0800306
307 if (extractor == NULL) {
308 return UNKNOWN_ERROR;
309 }
310
Gloria Wangd5770912010-06-22 13:55:38 -0700311 dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
Gloria Wangadc4d9c2011-02-08 13:24:08 -0800312 if (mDecryptHandle != NULL) {
313 CHECK(mDrmManagerClient);
314 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
315 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
316 }
Gloria Wangd5770912010-06-22 13:55:38 -0700317 }
318
Andreas Huber27366fc2009-11-20 09:32:46 -0800319 return setDataSource_l(extractor);
320}
321
322status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700323 // Attempt to approximate overall stream bitrate by summing all
324 // tracks' individual bitrates, if not all of them advertise bitrate,
325 // we have to fail.
326
327 int64_t totalBitRate = 0;
328
329 for (size_t i = 0; i < extractor->countTracks(); ++i) {
330 sp<MetaData> meta = extractor->getTrackMetaData(i);
331
332 int32_t bitrate;
333 if (!meta->findInt32(kKeyBitRate, &bitrate)) {
334 totalBitRate = -1;
335 break;
336 }
337
338 totalBitRate += bitrate;
339 }
340
341 mBitrate = totalBitRate;
342
343 LOGV("mBitrate = %lld bits/sec", mBitrate);
344
Andreas Huber27366fc2009-11-20 09:32:46 -0800345 bool haveAudio = false;
346 bool haveVideo = false;
347 for (size_t i = 0; i < extractor->countTracks(); ++i) {
348 sp<MetaData> meta = extractor->getTrackMetaData(i);
349
350 const char *mime;
351 CHECK(meta->findCString(kKeyMIMEType, &mime));
352
353 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800354 setVideoSource(extractor->getTrack(i));
355 haveVideo = true;
James Dong08adfd22011-01-16 11:30:13 -0800356
357 // Set the presentation/display size
358 int32_t displayWidth, displayHeight;
359 bool success = meta->findInt32(kKeyDisplayWidth, &displayWidth);
360 if (success) {
361 success = meta->findInt32(kKeyDisplayHeight, &displayHeight);
362 }
363 if (success) {
364 mDisplayWidth = displayWidth;
365 mDisplayHeight = displayHeight;
366 }
367
Andreas Huber27366fc2009-11-20 09:32:46 -0800368 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800369 setAudioSource(extractor->getTrack(i));
370 haveAudio = true;
Andreas Huber9fee0b22010-09-03 14:09:21 -0700371
Andreas Huber1913c1a2010-10-04 11:09:31 -0700372 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
373 // Only do this for vorbis audio, none of the other audio
374 // formats even support this ringtone specific hack and
375 // retrieving the metadata on some extractors may turn out
376 // to be very expensive.
377 sp<MetaData> fileMeta = extractor->getMetaData();
378 int32_t loop;
379 if (fileMeta != NULL
380 && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
381 mFlags |= AUTO_LOOPING;
382 }
Andreas Huber9fee0b22010-09-03 14:09:21 -0700383 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800384 }
385
386 if (haveAudio && haveVideo) {
387 break;
388 }
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
Andreas Huber3522b5a52010-01-22 14:36:53 -0800472 mVideoRenderer.clear();
473
Andreas Huber27366fc2009-11-20 09:32:46 -0800474 if (mVideoBuffer) {
475 mVideoBuffer->release();
476 mVideoBuffer = NULL;
477 }
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) {
485 mVideoSource->stop();
Andreas Huber98b48de2010-01-29 10:10:22 -0800486
487 // The following hack is necessary to ensure that the OMX
488 // component is completely released by the time we may try
489 // to instantiate it again.
490 wp<MediaSource> tmp = mVideoSource;
Andreas Huber27366fc2009-11-20 09:32:46 -0800491 mVideoSource.clear();
Andreas Huber98b48de2010-01-29 10:10:22 -0800492 while (tmp.promote() != NULL) {
493 usleep(1000);
494 }
495 IPCThreadState::self()->flushCommands();
Andreas Huber27366fc2009-11-20 09:32:46 -0800496 }
497
Andreas Huber27366fc2009-11-20 09:32:46 -0800498 mDurationUs = -1;
499 mFlags = 0;
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700500 mExtractorFlags = 0;
Andreas Huber27366fc2009-11-20 09:32:46 -0800501 mTimeSourceDeltaUs = 0;
502 mVideoTimeUs = 0;
503
Andreas Hubera2c29972011-02-24 12:05:40 -0800504 mSeeking = NO_SEEK;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700505 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800506 mSeekTimeUs = 0;
Andreas Huberb9e63832010-01-26 16:20:10 -0800507
Andreas Huberffdf4782010-02-09 14:05:43 -0800508 mUri.setTo("");
509 mUriHeaders.clear();
Andreas Huberba7ec912010-02-12 10:42:02 -0800510
511 mFileSource.clear();
512
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700513 mBitrate = -1;
Andreas Huber27366fc2009-11-20 09:32:46 -0800514}
515
Andreas Huber6be780e2010-02-08 14:40:30 -0800516void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
Andreas Hubera3f43842010-01-21 10:28:45 -0800517 if (mListener != NULL) {
518 sp<MediaPlayerBase> listener = mListener.promote();
519
520 if (listener != NULL) {
Andreas Huber6be780e2010-02-08 14:40:30 -0800521 listener->sendEvent(msg, ext1, ext2);
Andreas Hubera3f43842010-01-21 10:28:45 -0800522 }
523 }
524}
525
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700526bool AwesomePlayer::getBitrate(int64_t *bitrate) {
James Dongb1262a82010-11-16 14:04:54 -0800527 off64_t size;
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700528 if (mDurationUs >= 0 && mCachedSource != NULL
529 && mCachedSource->getSize(&size) == OK) {
530 *bitrate = size * 8000000ll / mDurationUs; // in bits/sec
531 return true;
532 }
533
534 if (mBitrate >= 0) {
535 *bitrate = mBitrate;
536 return true;
537 }
538
539 *bitrate = 0;
540
541 return false;
542}
543
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700544// Returns true iff cached duration is available/applicable.
545bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700546 int64_t bitrate;
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700547
548 if (mRTSPController != NULL) {
549 *durationUs = mRTSPController->getQueueDurationUs(eos);
550 return true;
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700551 } else if (mCachedSource != NULL && getBitrate(&bitrate)) {
Bryan Mawhinneye26275b2011-01-18 19:12:21 +0000552 status_t finalStatus;
553 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700554 *durationUs = cachedDataRemaining * 8000000ll / bitrate;
Bryan Mawhinneye26275b2011-01-18 19:12:21 +0000555 *eos = (finalStatus != OK);
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700556 return true;
557 }
558
559 return false;
560}
561
Andreas Huber10b920c2010-11-11 15:37:17 -0800562void AwesomePlayer::ensureCacheIsFetching_l() {
563 if (mCachedSource != NULL) {
564 mCachedSource->resumeFetchingIfNecessary();
565 }
566}
567
Andreas Huber52c78322011-01-11 15:05:28 -0800568void AwesomePlayer::onVideoLagUpdate() {
569 Mutex::Autolock autoLock(mLock);
570 if (!mVideoLagEventPending) {
571 return;
572 }
573 mVideoLagEventPending = false;
574
575 int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs();
576 int64_t videoLateByUs = audioTimeUs - mVideoTimeUs;
577
Andreas Huber16ede3c2011-03-25 13:03:14 -0700578 if (!(mFlags & VIDEO_AT_EOS) && videoLateByUs > 300000ll) {
Andreas Huber52c78322011-01-11 15:05:28 -0800579 LOGV("video late by %lld ms.", videoLateByUs / 1000ll);
580
581 notifyListener_l(
582 MEDIA_INFO,
583 MEDIA_INFO_VIDEO_TRACK_LAGGING,
584 videoLateByUs / 1000ll);
585 }
586
587 postVideoLagEvent_l();
588}
589
Andreas Huberb9e63832010-01-26 16:20:10 -0800590void AwesomePlayer::onBufferingUpdate() {
591 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800592 if (!mBufferingEventPending) {
593 return;
594 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800595 mBufferingEventPending = false;
596
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700597 if (mCachedSource != NULL) {
Bryan Mawhinneye26275b2011-01-18 19:12:21 +0000598 status_t finalStatus;
599 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
600 bool eos = (finalStatus != OK);
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700601
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700602 if (eos) {
Bryan Mawhinneye26275b2011-01-18 19:12:21 +0000603 if (finalStatus == ERROR_END_OF_STREAM) {
604 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
605 }
Andreas Huber05f67872010-10-04 11:36:39 -0700606 if (mFlags & PREPARING) {
607 LOGV("cache has reached EOS, prepare is done.");
608 finishAsyncPrepare_l();
609 }
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700610 } else {
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700611 int64_t bitrate;
612 if (getBitrate(&bitrate)) {
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700613 size_t cachedSize = mCachedSource->cachedSize();
614 int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
615
616 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
617 if (percentage > 100) {
618 percentage = 100;
619 }
620
621 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
622 } else {
623 // We don't know the bitrate of the stream, use absolute size
624 // limits to maintain the cache.
625
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700626 if ((mFlags & PLAYING) && !eos
627 && (cachedDataRemaining < kLowWaterMarkBytes)) {
628 LOGI("cache is running low (< %d) , pausing.",
629 kLowWaterMarkBytes);
630 mFlags |= CACHE_UNDERRUN;
631 pause_l();
Andreas Huber10b920c2010-11-11 15:37:17 -0800632 ensureCacheIsFetching_l();
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700633 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
634 } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
635 if (mFlags & CACHE_UNDERRUN) {
636 LOGI("cache has filled up (> %d), resuming.",
637 kHighWaterMarkBytes);
638 mFlags &= ~CACHE_UNDERRUN;
639 play_l();
640 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
641 } else if (mFlags & PREPARING) {
642 LOGV("cache has filled up (> %d), prepare is done",
643 kHighWaterMarkBytes);
644 finishAsyncPrepare_l();
645 }
646 }
647 }
648 }
649 }
650
651 int64_t cachedDurationUs;
652 bool eos;
653 if (getCachedDuration_l(&cachedDurationUs, &eos)) {
Andreas Huber10b920c2010-11-11 15:37:17 -0800654 LOGV("cachedDurationUs = %.2f secs, eos=%d",
655 cachedDurationUs / 1E6, eos);
656
Andreas Huberb2934b12011-02-08 10:18:41 -0800657 int64_t highWaterMarkUs =
658 (mRTSPController != NULL) ? kHighWaterMarkRTSPUs : kHighWaterMarkUs;
659
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700660 if ((mFlags & PLAYING) && !eos
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700661 && (cachedDurationUs < kLowWaterMarkUs)) {
662 LOGI("cache is running low (%.2f secs) , pausing.",
663 cachedDurationUs / 1E6);
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700664 mFlags |= CACHE_UNDERRUN;
665 pause_l();
Andreas Huber10b920c2010-11-11 15:37:17 -0800666 ensureCacheIsFetching_l();
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700667 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
Andreas Huberb2934b12011-02-08 10:18:41 -0800668 } else if (eos || cachedDurationUs > highWaterMarkUs) {
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700669 if (mFlags & CACHE_UNDERRUN) {
670 LOGI("cache has filled up (%.2f secs), resuming.",
671 cachedDurationUs / 1E6);
672 mFlags &= ~CACHE_UNDERRUN;
673 play_l();
674 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
675 } else if (mFlags & PREPARING) {
676 LOGV("cache has filled up (%.2f secs), prepare is done",
677 cachedDurationUs / 1E6);
678 finishAsyncPrepare_l();
Andreas Huberc23296e2010-08-25 12:31:48 -0700679 }
Andreas Huberc23296e2010-08-25 12:31:48 -0700680 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800681 }
Andreas Huber4d61f602010-06-10 11:17:50 -0700682
Andreas Huber4d61f602010-06-10 11:17:50 -0700683 postBufferingEvent_l();
Andreas Huberb9e63832010-01-26 16:20:10 -0800684}
685
Andreas Huber27366fc2009-11-20 09:32:46 -0800686void AwesomePlayer::onStreamDone() {
687 // Posted whenever any stream finishes playing.
688
689 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800690 if (!mStreamDoneEventPending) {
691 return;
692 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800693 mStreamDoneEventPending = false;
694
Andreas Huberd6c421f2011-02-16 09:05:38 -0800695 if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
Andreas Huber971305d2010-07-07 13:35:27 -0700696 LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
697
698 notifyListener_l(
699 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
700
Andreas Huberc743f452010-10-05 10:25:34 -0700701 pause_l(true /* at eos */);
Andreas Huber971305d2010-07-07 13:35:27 -0700702
703 mFlags |= AT_EOS;
704 return;
705 }
706
707 const bool allDone =
708 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
709 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
710
711 if (!allDone) {
712 return;
713 }
714
Andreas Huber9fee0b22010-09-03 14:09:21 -0700715 if (mFlags & (LOOPING | AUTO_LOOPING)) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800716 seekTo_l(0);
717
Andreas Huber7085b6842010-02-03 16:02:02 -0800718 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800719 postVideoEvent_l();
720 }
721 } else {
Andreas Huber971305d2010-07-07 13:35:27 -0700722 LOGV("MEDIA_PLAYBACK_COMPLETE");
723 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800724
Andreas Huberc743f452010-10-05 10:25:34 -0700725 pause_l(true /* at eos */);
Andreas Huber406a18b2010-02-18 16:45:13 -0800726
727 mFlags |= AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800728 }
729}
730
731status_t AwesomePlayer::play() {
732 Mutex::Autolock autoLock(mLock);
Andreas Huber4d61f602010-06-10 11:17:50 -0700733
734 mFlags &= ~CACHE_UNDERRUN;
735
Andreas Huberba7ec912010-02-12 10:42:02 -0800736 return play_l();
737}
Andreas Huber27366fc2009-11-20 09:32:46 -0800738
Andreas Huberba7ec912010-02-12 10:42:02 -0800739status_t AwesomePlayer::play_l() {
Andreas Huber0a84f4f2011-02-07 11:43:12 -0800740 mFlags &= ~SEEK_PREVIEW;
741
Andreas Huber27366fc2009-11-20 09:32:46 -0800742 if (mFlags & PLAYING) {
743 return OK;
744 }
745
Andreas Huberffdf4782010-02-09 14:05:43 -0800746 if (!(mFlags & PREPARED)) {
747 status_t err = prepare_l();
748
749 if (err != OK) {
750 return err;
751 }
752 }
753
Andreas Huber27366fc2009-11-20 09:32:46 -0800754 mFlags |= PLAYING;
755 mFlags |= FIRST_FRAME;
756
Gloria Wang95dbffb2010-11-04 17:38:39 -0700757 if (mDecryptHandle != NULL) {
758 int64_t position;
759 getPosition(&position);
760 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
761 Playback::START, position / 1000);
762 }
763
Andreas Huber27366fc2009-11-20 09:32:46 -0800764 if (mAudioSource != NULL) {
765 if (mAudioPlayer == NULL) {
766 if (mAudioSink != NULL) {
Andreas Huber2b359ed2010-09-28 11:56:39 -0700767 mAudioPlayer = new AudioPlayer(mAudioSink, this);
Andreas Huber27366fc2009-11-20 09:32:46 -0800768 mAudioPlayer->setSource(mAudioSource);
Andreas Huberdc9927d2010-03-08 15:46:13 -0800769
Andreas Huber27366fc2009-11-20 09:32:46 -0800770 mTimeSource = mAudioPlayer;
771
Andreas Huber5bd3bb42011-03-16 10:41:25 -0700772 // If there was a seek request before we ever started,
773 // honor the request now.
774 // Make sure to do this before starting the audio player
775 // to avoid a race condition.
776 seekAudioIfNecessary_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800777 }
Andreas Huberce8a1012011-02-11 13:09:36 -0800778 }
779
780 CHECK(!(mFlags & AUDIO_RUNNING));
781
782 if (mVideoSource == NULL) {
783 status_t err = startAudioPlayer_l();
784
785 if (err != OK) {
786 delete mAudioPlayer;
787 mAudioPlayer = NULL;
788
789 mFlags &= ~(PLAYING | FIRST_FRAME);
790
791 if (mDecryptHandle != NULL) {
792 mDrmManagerClient->setPlaybackStatus(
793 mDecryptHandle, Playback::STOP, 0);
794 }
795
796 return err;
797 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800798 }
799 }
800
801 if (mTimeSource == NULL && mAudioPlayer == NULL) {
Andreas Huber971305d2010-07-07 13:35:27 -0700802 mTimeSource = &mSystemTimeSource;
Andreas Huber27366fc2009-11-20 09:32:46 -0800803 }
804
805 if (mVideoSource != NULL) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800806 // Kick off video playback
807 postVideoEvent_l();
Andreas Huber52c78322011-01-11 15:05:28 -0800808
809 if (mAudioSource != NULL && mVideoSource != NULL) {
810 postVideoLagEvent_l();
811 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800812 }
813
Andreas Huber406a18b2010-02-18 16:45:13 -0800814 if (mFlags & AT_EOS) {
815 // Legacy behaviour, if a stream finishes playing and then
816 // is started again, we play from the start...
817 seekTo_l(0);
818 }
819
Gloria Wangd211f412011-02-19 18:37:57 -0800820 uint32_t params = IMediaPlayerService::kBatteryDataCodecStarted
821 | IMediaPlayerService::kBatteryDataTrackDecoder;
822 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
823 params |= IMediaPlayerService::kBatteryDataTrackAudio;
824 }
825 if (mVideoSource != NULL) {
826 params |= IMediaPlayerService::kBatteryDataTrackVideo;
827 }
828 addBatteryData(params);
829
Andreas Huber27366fc2009-11-20 09:32:46 -0800830 return OK;
831}
832
Andreas Huberce8a1012011-02-11 13:09:36 -0800833status_t AwesomePlayer::startAudioPlayer_l() {
834 CHECK(!(mFlags & AUDIO_RUNNING));
835
836 if (mAudioSource == NULL || mAudioPlayer == NULL) {
837 return OK;
838 }
839
840 if (!(mFlags & AUDIOPLAYER_STARTED)) {
841 mFlags |= AUDIOPLAYER_STARTED;
842
843 // We've already started the MediaSource in order to enable
844 // the prefetcher to read its data.
845 status_t err = mAudioPlayer->start(
846 true /* sourceAlreadyStarted */);
847
848 if (err != OK) {
849 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
850 return err;
851 }
852 } 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
883 int32_t usableWidth = cropRight - cropLeft + 1;
884 int32_t usableHeight = cropBottom - cropTop + 1;
James Dong08adfd22011-01-16 11:30:13 -0800885 if (mDisplayWidth != 0) {
886 usableWidth = mDisplayWidth;
887 }
888 if (mDisplayHeight != 0) {
889 usableHeight = mDisplayHeight;
890 }
Andreas Hubere3c01832010-08-16 08:49:37 -0700891
Andreas Huber940c8662010-11-16 15:26:30 -0800892 int32_t rotationDegrees;
893 if (!mVideoTrack->getFormat()->findInt32(
894 kKeyRotation, &rotationDegrees)) {
895 rotationDegrees = 0;
896 }
897
898 if (rotationDegrees == 90 || rotationDegrees == 270) {
899 notifyListener_l(
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800900 MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
Andreas Huber940c8662010-11-16 15:26:30 -0800901 } else {
902 notifyListener_l(
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800903 MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
Andreas Huber940c8662010-11-16 15:26:30 -0800904 }
Andreas Hubere3c01832010-08-16 08:49:37 -0700905}
906
Andreas Huber27366fc2009-11-20 09:32:46 -0800907void AwesomePlayer::initRenderer_l() {
Glenn Kastencc562a32011-02-08 17:26:17 -0800908 if (mNativeWindow == NULL) {
Andreas Huberc23dabf2010-11-16 13:05:53 -0800909 return;
910 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800911
Andreas Huberc23dabf2010-11-16 13:05:53 -0800912 sp<MetaData> meta = mVideoSource->getFormat();
Andreas Huber27366fc2009-11-20 09:32:46 -0800913
Andreas Huberc23dabf2010-11-16 13:05:53 -0800914 int32_t format;
915 const char *component;
916 int32_t decodedWidth, decodedHeight;
917 CHECK(meta->findInt32(kKeyColorFormat, &format));
918 CHECK(meta->findCString(kKeyDecoderComponent, &component));
919 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
920 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
Andreas Hubera67d5382009-12-10 15:32:12 -0800921
Andreas Huber940c8662010-11-16 15:26:30 -0800922 int32_t rotationDegrees;
923 if (!mVideoTrack->getFormat()->findInt32(
924 kKeyRotation, &rotationDegrees)) {
925 rotationDegrees = 0;
926 }
927
Andreas Huberc23dabf2010-11-16 13:05:53 -0800928 mVideoRenderer.clear();
Andreas Hubera67d5382009-12-10 15:32:12 -0800929
Andreas Huberc23dabf2010-11-16 13:05:53 -0800930 // Must ensure that mVideoRenderer's destructor is actually executed
931 // before creating a new one.
932 IPCThreadState::self()->flushCommands();
933
934 if (USE_SURFACE_ALLOC && strncmp(component, "OMX.", 4) == 0) {
935 // Hardware decoders avoid the CPU color conversion by decoding
936 // directly to ANativeBuffers, so we must use a renderer that
937 // just pushes those buffers to the ANativeWindow.
Andreas Huber940c8662010-11-16 15:26:30 -0800938 mVideoRenderer =
Glenn Kastencc562a32011-02-08 17:26:17 -0800939 new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees);
Andreas Huberc23dabf2010-11-16 13:05:53 -0800940 } else {
941 // Other decoders are instantiated locally and as a consequence
942 // allocate their buffers in local address space. This renderer
943 // then performs a color conversion and copy to get the data
944 // into the ANativeBuffer.
Glenn Kastencc562a32011-02-08 17:26:17 -0800945 mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta);
Andreas Huber27366fc2009-11-20 09:32:46 -0800946 }
947}
948
949status_t AwesomePlayer::pause() {
950 Mutex::Autolock autoLock(mLock);
Andreas Huber4d61f602010-06-10 11:17:50 -0700951
952 mFlags &= ~CACHE_UNDERRUN;
953
Andreas Huber27366fc2009-11-20 09:32:46 -0800954 return pause_l();
955}
956
Andreas Huberc743f452010-10-05 10:25:34 -0700957status_t AwesomePlayer::pause_l(bool at_eos) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800958 if (!(mFlags & PLAYING)) {
959 return OK;
960 }
961
Andreas Huberb9e63832010-01-26 16:20:10 -0800962 cancelPlayerEvents(true /* keepBufferingGoing */);
Andreas Huber27366fc2009-11-20 09:32:46 -0800963
Andreas Huberce8a1012011-02-11 13:09:36 -0800964 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Andreas Huberc743f452010-10-05 10:25:34 -0700965 if (at_eos) {
966 // If we played the audio stream to completion we
967 // want to make sure that all samples remaining in the audio
968 // track's queue are played out.
969 mAudioPlayer->pause(true /* playPendingSamples */);
970 } else {
971 mAudioPlayer->pause();
972 }
Andreas Huberce8a1012011-02-11 13:09:36 -0800973
974 mFlags &= ~AUDIO_RUNNING;
Andreas Huber27366fc2009-11-20 09:32:46 -0800975 }
976
977 mFlags &= ~PLAYING;
978
Gloria Wangd5770912010-06-22 13:55:38 -0700979 if (mDecryptHandle != NULL) {
980 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
981 Playback::PAUSE, 0);
982 }
983
Gloria Wangd211f412011-02-19 18:37:57 -0800984 uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
985 if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
986 params |= IMediaPlayerService::kBatteryDataTrackAudio;
987 }
988 if (mVideoSource != NULL) {
989 params |= IMediaPlayerService::kBatteryDataTrackVideo;
990 }
991
992 addBatteryData(params);
993
Andreas Huber27366fc2009-11-20 09:32:46 -0800994 return OK;
995}
996
997bool AwesomePlayer::isPlaying() const {
Andreas Huber4d61f602010-06-10 11:17:50 -0700998 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
Andreas Huber27366fc2009-11-20 09:32:46 -0800999}
1000
Andreas Hubere3c01832010-08-16 08:49:37 -07001001void AwesomePlayer::setSurface(const sp<Surface> &surface) {
1002 Mutex::Autolock autoLock(mLock);
1003
1004 mSurface = surface;
Glenn Kastencc562a32011-02-08 17:26:17 -08001005 mNativeWindow = surface;
1006}
1007
1008void AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
1009 Mutex::Autolock autoLock(mLock);
1010
1011 mSurface.clear();
1012 if (surfaceTexture != NULL) {
1013 mNativeWindow = new SurfaceTextureClient(surfaceTexture);
1014 }
1015
Andreas Hubere3c01832010-08-16 08:49:37 -07001016}
1017
Andreas Huber27366fc2009-11-20 09:32:46 -08001018void AwesomePlayer::setAudioSink(
1019 const sp<MediaPlayerBase::AudioSink> &audioSink) {
1020 Mutex::Autolock autoLock(mLock);
1021
1022 mAudioSink = audioSink;
1023}
1024
1025status_t AwesomePlayer::setLooping(bool shouldLoop) {
1026 Mutex::Autolock autoLock(mLock);
1027
1028 mFlags = mFlags & ~LOOPING;
1029
1030 if (shouldLoop) {
1031 mFlags |= LOOPING;
1032 }
1033
1034 return OK;
1035}
1036
1037status_t AwesomePlayer::getDuration(int64_t *durationUs) {
Andreas Huber252573c2010-03-26 10:17:17 -07001038 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001039
1040 if (mDurationUs < 0) {
1041 return UNKNOWN_ERROR;
1042 }
1043
1044 *durationUs = mDurationUs;
1045
1046 return OK;
1047}
1048
1049status_t AwesomePlayer::getPosition(int64_t *positionUs) {
Andreas Hubereeb97d92010-08-27 13:29:08 -07001050 if (mRTSPController != NULL) {
1051 *positionUs = mRTSPController->getNormalPlayTimeUs();
1052 }
Andreas Hubera2c29972011-02-24 12:05:40 -08001053 else if (mSeeking != NO_SEEK) {
Andreas Huberddb709c2010-04-07 10:24:35 -07001054 *positionUs = mSeekTimeUs;
Andreas Huber16ede3c2011-03-25 13:03:14 -07001055 } else if (mVideoSource != NULL
1056 && (mAudioPlayer == NULL || !(mFlags & VIDEO_AT_EOS))) {
Andreas Huber252573c2010-03-26 10:17:17 -07001057 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001058 *positionUs = mVideoTimeUs;
1059 } else if (mAudioPlayer != NULL) {
1060 *positionUs = mAudioPlayer->getMediaTimeUs();
1061 } else {
1062 *positionUs = 0;
1063 }
1064
1065 return OK;
1066}
1067
1068status_t AwesomePlayer::seekTo(int64_t timeUs) {
Andreas Huber10b9b3f2010-10-08 10:16:24 -07001069 if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
Andreas Huber62f7ffe2010-05-06 10:18:05 -07001070 Mutex::Autolock autoLock(mLock);
1071 return seekTo_l(timeUs);
1072 }
1073
1074 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -08001075}
1076
Andreas Huber0c46b692010-10-08 15:21:08 -07001077// static
1078void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) {
1079 static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone();
1080}
1081
1082void AwesomePlayer::onRTSPSeekDone() {
1083 notifyListener_l(MEDIA_SEEK_COMPLETE);
1084 mSeekNotificationSent = true;
1085}
1086
Andreas Huber27366fc2009-11-20 09:32:46 -08001087status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
Andreas Hubere0dd7d32010-08-24 14:33:58 -07001088 if (mRTSPController != NULL) {
Andreas Huber0c46b692010-10-08 15:21:08 -07001089 mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this);
Andreas Hubere0dd7d32010-08-24 14:33:58 -07001090 return OK;
1091 }
1092
Andreas Huber4d61f602010-06-10 11:17:50 -07001093 if (mFlags & CACHE_UNDERRUN) {
1094 mFlags &= ~CACHE_UNDERRUN;
1095 play_l();
1096 }
1097
Andreas Huber16ede3c2011-03-25 13:03:14 -07001098 if ((mFlags & PLAYING) && mVideoSource != NULL && (mFlags & VIDEO_AT_EOS)) {
1099 // Video playback completed before, there's no pending
1100 // video event right now. In order for this new seek
1101 // to be honored, we need to post one.
1102
1103 postVideoEvent_l();
1104 }
1105
Andreas Hubera2c29972011-02-24 12:05:40 -08001106 mSeeking = SEEK;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001107 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -08001108 mSeekTimeUs = timeUs;
Andreas Huber971305d2010-07-07 13:35:27 -07001109 mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
Andreas Huber27366fc2009-11-20 09:32:46 -08001110
1111 seekAudioIfNecessary_l();
1112
Andreas Huber8e2b9412010-03-31 09:40:15 -07001113 if (!(mFlags & PLAYING)) {
1114 LOGV("seeking while paused, sending SEEK_COMPLETE notification"
1115 " immediately.");
1116
1117 notifyListener_l(MEDIA_SEEK_COMPLETE);
1118 mSeekNotificationSent = true;
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001119
1120 if ((mFlags & PREPARED) && mVideoSource != NULL) {
1121 mFlags |= SEEK_PREVIEW;
1122 postVideoEvent_l();
1123 }
Andreas Huber8e2b9412010-03-31 09:40:15 -07001124 }
1125
Andreas Huber27366fc2009-11-20 09:32:46 -08001126 return OK;
1127}
1128
1129void AwesomePlayer::seekAudioIfNecessary_l() {
Andreas Hubera2c29972011-02-24 12:05:40 -08001130 if (mSeeking != NO_SEEK && mVideoSource == NULL && mAudioPlayer != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001131 mAudioPlayer->seekTo(mSeekTimeUs);
1132
Andreas Huber70d10c02010-02-03 11:37:29 -08001133 mWatchForAudioSeekComplete = true;
1134 mWatchForAudioEOS = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001135 mSeekNotificationSent = false;
Gloria Wangd5770912010-06-22 13:55:38 -07001136
1137 if (mDecryptHandle != NULL) {
1138 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1139 Playback::PAUSE, 0);
1140 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1141 Playback::START, mSeekTimeUs / 1000);
1142 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001143 }
1144}
1145
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001146void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
1147 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001148
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001149 mAudioTrack = source;
1150}
1151
1152status_t AwesomePlayer::initAudioDecoder() {
1153 sp<MetaData> meta = mAudioTrack->getFormat();
Andreas Huberc79827a2010-01-05 10:54:55 -08001154
1155 const char *mime;
1156 CHECK(meta->findCString(kKeyMIMEType, &mime));
1157
1158 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001159 mAudioSource = mAudioTrack;
Andreas Huberc79827a2010-01-05 10:54:55 -08001160 } else {
1161 mAudioSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001162 mClient.interface(), mAudioTrack->getFormat(),
Andreas Huberc79827a2010-01-05 10:54:55 -08001163 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001164 mAudioTrack);
Andreas Huberc79827a2010-01-05 10:54:55 -08001165 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001166
1167 if (mAudioSource != NULL) {
1168 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001169 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -07001170 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001171 if (mDurationUs < 0 || durationUs > mDurationUs) {
1172 mDurationUs = durationUs;
1173 }
1174 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001175
Andreas Huber3c78a1b2010-05-13 09:15:21 -07001176 status_t err = mAudioSource->start();
1177
1178 if (err != OK) {
1179 mAudioSource.clear();
1180 return err;
1181 }
Andreas Huberd0332ad2010-04-12 16:05:57 -07001182 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
1183 // For legacy reasons we're simply going to ignore the absence
1184 // of an audio decoder for QCELP instead of aborting playback
1185 // altogether.
1186 return OK;
1187 }
Andreas Huberdc9927d2010-03-08 15:46:13 -08001188
Andreas Huber27366fc2009-11-20 09:32:46 -08001189 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
1190}
1191
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001192void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
1193 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001194
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001195 mVideoTrack = source;
1196}
1197
Andreas Huber4c19bf92010-09-08 14:32:20 -07001198status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
Glenn Kastenb8763f62011-01-28 12:37:51 -08001199
1200 // Either the application or the DRM system can independently say
1201 // that there must be a hardware-protected path to an external video sink.
1202 // For now we always require a hardware-protected path to external video sink
1203 // if content is DRMed, but eventually this could be optional per DRM agent.
1204 // When the application wants protection, then
1205 // (USE_SURFACE_ALLOC && (mSurface != 0) &&
1206 // (mSurface->getFlags() & ISurfaceComposer::eProtectedByApp))
1207 // will be true, but that part is already handled by SurfaceFlinger.
Glenn Kasten1b11b642011-03-23 14:34:31 -07001208
1209#ifdef DEBUG_HDCP
1210 // For debugging, we allow a system property to control the protected usage.
1211 // In case of uninitialized or unexpected property, we default to "DRM only".
1212 bool setProtectionBit = false;
1213 char value[PROPERTY_VALUE_MAX];
1214 if (property_get("persist.sys.hdcp_checking", value, NULL)) {
1215 if (!strcmp(value, "never")) {
1216 // nop
1217 } else if (!strcmp(value, "always")) {
1218 setProtectionBit = true;
1219 } else if (!strcmp(value, "drm-only")) {
1220 if (mDecryptHandle != NULL) {
1221 setProtectionBit = true;
1222 }
1223 // property value is empty, or unexpected value
1224 } else {
1225 if (mDecryptHandle != NULL) {
1226 setProtectionBit = true;
1227 }
1228 }
1229 // can' read property value
1230 } else {
1231 if (mDecryptHandle != NULL) {
1232 setProtectionBit = true;
1233 }
1234 }
1235 // note that usage bit is already cleared, so no need to clear it in the "else" case
1236 if (setProtectionBit) {
1237 flags |= OMXCodec::kEnableGrallocUsageProtected;
1238 }
1239#else
Glenn Kastenb8763f62011-01-28 12:37:51 -08001240 if (mDecryptHandle != NULL) {
1241 flags |= OMXCodec::kEnableGrallocUsageProtected;
1242 }
Glenn Kasten1b11b642011-03-23 14:34:31 -07001243#endif
Glenn Kastenb8763f62011-01-28 12:37:51 -08001244 LOGV("initVideoDecoder flags=0x%x", flags);
Andreas Huber27366fc2009-11-20 09:32:46 -08001245 mVideoSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001246 mClient.interface(), mVideoTrack->getFormat(),
Andreas Huber27366fc2009-11-20 09:32:46 -08001247 false, // createEncoder
Andreas Huber57648e42010-08-04 10:14:30 -07001248 mVideoTrack,
Glenn Kastencc562a32011-02-08 17:26:17 -08001249 NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001250
1251 if (mVideoSource != NULL) {
1252 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001253 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -07001254 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001255 if (mDurationUs < 0 || durationUs > mDurationUs) {
1256 mDurationUs = durationUs;
1257 }
1258 }
1259
Andreas Huber1919e5a2010-05-20 10:37:06 -07001260 status_t err = mVideoSource->start();
1261
1262 if (err != OK) {
1263 mVideoSource.clear();
1264 return err;
1265 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001266 }
1267
1268 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
1269}
1270
Andreas Huber4d450a82010-10-19 09:34:44 -07001271void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
Andreas Hubera2c29972011-02-24 12:05:40 -08001272 if (mSeeking == SEEK_VIDEO_ONLY) {
1273 mSeeking = NO_SEEK;
1274 return;
1275 }
1276
1277 if (mSeeking == NO_SEEK || (mFlags & SEEK_PREVIEW)) {
Andreas Huber4d450a82010-10-19 09:34:44 -07001278 return;
1279 }
1280
1281 if (mAudioPlayer != NULL) {
Jamie Gennis6913c612010-10-20 15:55:43 -07001282 LOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
Andreas Huber4d450a82010-10-19 09:34:44 -07001283
1284 // If we don't have a video time, seek audio to the originally
1285 // requested seek time instead.
1286
1287 mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
Andreas Huber4d450a82010-10-19 09:34:44 -07001288 mWatchForAudioSeekComplete = true;
Andreas Huber16ede3c2011-03-25 13:03:14 -07001289 mWatchForAudioEOS = true;
Andreas Huber4d450a82010-10-19 09:34:44 -07001290 } else if (!mSeekNotificationSent) {
1291 // If we're playing video only, report seek complete now,
1292 // otherwise audio player will notify us later.
1293 notifyListener_l(MEDIA_SEEK_COMPLETE);
1294 }
1295
1296 mFlags |= FIRST_FRAME;
Andreas Hubera2c29972011-02-24 12:05:40 -08001297 mSeeking = NO_SEEK;
Andreas Huber4d450a82010-10-19 09:34:44 -07001298 mSeekNotificationSent = false;
Gloria Wang3f9a8192010-10-29 14:50:17 -07001299
1300 if (mDecryptHandle != NULL) {
1301 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1302 Playback::PAUSE, 0);
1303 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1304 Playback::START, videoTimeUs / 1000);
1305 }
Andreas Huber4d450a82010-10-19 09:34:44 -07001306}
1307
Andreas Huber6be780e2010-02-08 14:40:30 -08001308void AwesomePlayer::onVideoEvent() {
Andreas Huber27366fc2009-11-20 09:32:46 -08001309 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -08001310 if (!mVideoEventPending) {
1311 // The event has been cancelled in reset_l() but had already
1312 // been scheduled for execution at that time.
1313 return;
1314 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001315 mVideoEventPending = false;
1316
Andreas Hubera2c29972011-02-24 12:05:40 -08001317 if (mSeeking != NO_SEEK) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001318 if (mVideoBuffer) {
1319 mVideoBuffer->release();
1320 mVideoBuffer = NULL;
1321 }
Andreas Huber4d61f602010-06-10 11:17:50 -07001322
Andreas Hubera2c29972011-02-24 12:05:40 -08001323 if (mSeeking == SEEK && mCachedSource != NULL && mAudioSource != NULL
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001324 && !(mFlags & SEEK_PREVIEW)) {
Andreas Huber4d61f602010-06-10 11:17:50 -07001325 // We're going to seek the video source first, followed by
1326 // the audio source.
1327 // In order to avoid jumps in the DataSource offset caused by
1328 // the audio codec prefetching data from the old locations
1329 // while the video codec is already reading data from the new
1330 // locations, we'll "pause" the audio source, causing it to
1331 // stop reading input data until a subsequent seek.
1332
Andreas Huberce8a1012011-02-11 13:09:36 -08001333 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Andreas Huber4d61f602010-06-10 11:17:50 -07001334 mAudioPlayer->pause();
Andreas Huberce8a1012011-02-11 13:09:36 -08001335
1336 mFlags &= ~AUDIO_RUNNING;
Andreas Huber4d61f602010-06-10 11:17:50 -07001337 }
1338 mAudioSource->pause();
1339 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001340 }
1341
1342 if (!mVideoBuffer) {
1343 MediaSource::ReadOptions options;
Andreas Hubera2c29972011-02-24 12:05:40 -08001344 if (mSeeking != NO_SEEK) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001345 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
1346
Andreas Huber6624c9f2010-07-20 15:04:28 -07001347 options.setSeekTo(
Andreas Hubera2c29972011-02-24 12:05:40 -08001348 mSeekTimeUs,
1349 mSeeking == SEEK_VIDEO_ONLY
1350 ? MediaSource::ReadOptions::SEEK_NEXT_SYNC
1351 : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
Andreas Huber27366fc2009-11-20 09:32:46 -08001352 }
1353 for (;;) {
1354 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberb1f5ee42009-12-14 15:34:11 -08001355 options.clearSeekTo();
Andreas Huber27366fc2009-11-20 09:32:46 -08001356
1357 if (err != OK) {
Andreas Huber52b52cd2010-11-23 11:41:34 -08001358 CHECK(mVideoBuffer == NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001359
1360 if (err == INFO_FORMAT_CHANGED) {
1361 LOGV("VideoSource signalled format change.");
1362
Andreas Hubere3c01832010-08-16 08:49:37 -07001363 notifyVideoSize_l();
1364
Andreas Huber7085b6842010-02-03 16:02:02 -08001365 if (mVideoRenderer != NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001366 mVideoRendererIsPreview = false;
Andreas Huber7085b6842010-02-03 16:02:02 -08001367 initRenderer_l();
1368 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001369 continue;
1370 }
1371
Andreas Huber4d450a82010-10-19 09:34:44 -07001372 // So video playback is complete, but we may still have
1373 // a seek request pending that needs to be applied
1374 // to the audio track.
Andreas Hubera2c29972011-02-24 12:05:40 -08001375 if (mSeeking != NO_SEEK) {
Andreas Huber4d450a82010-10-19 09:34:44 -07001376 LOGV("video stream ended while seeking!");
1377 }
1378 finishSeekIfNecessary(-1);
1379
Andreas Huber16ede3c2011-03-25 13:03:14 -07001380 if (mAudioPlayer != NULL
1381 && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1382 startAudioPlayer_l();
1383 }
1384
Andreas Huber971305d2010-07-07 13:35:27 -07001385 mFlags |= VIDEO_AT_EOS;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001386 postStreamDoneEvent_l(err);
Andreas Huber27366fc2009-11-20 09:32:46 -08001387 return;
1388 }
1389
Andreas Hubera67d5382009-12-10 15:32:12 -08001390 if (mVideoBuffer->range_length() == 0) {
Andreas Huber6ddcf012009-12-10 15:32:12 -08001391 // Some decoders, notably the PV AVC software decoder
1392 // return spurious empty buffers that we just want to ignore.
1393
Andreas Hubera67d5382009-12-10 15:32:12 -08001394 mVideoBuffer->release();
1395 mVideoBuffer = NULL;
1396 continue;
1397 }
1398
Andreas Huber27366fc2009-11-20 09:32:46 -08001399 break;
1400 }
1401 }
1402
1403 int64_t timeUs;
1404 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1405
Andreas Hubera2c29972011-02-24 12:05:40 -08001406 if (mSeeking == SEEK_VIDEO_ONLY) {
1407 if (mSeekTimeUs > timeUs) {
1408 LOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us",
1409 mSeekTimeUs, timeUs);
1410 }
1411 }
1412
Andreas Huber252573c2010-03-26 10:17:17 -07001413 {
1414 Mutex::Autolock autoLock(mMiscStateLock);
1415 mVideoTimeUs = timeUs;
1416 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001417
Andreas Hubera2c29972011-02-24 12:05:40 -08001418 SeekType wasSeeking = mSeeking;
Andreas Huber4d450a82010-10-19 09:34:44 -07001419 finishSeekIfNecessary(timeUs);
Andreas Huber27366fc2009-11-20 09:32:46 -08001420
Andreas Huberce8a1012011-02-11 13:09:36 -08001421 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1422 status_t err = startAudioPlayer_l();
1423 if (err != OK) {
1424 LOGE("Startung the audio player failed w/ err %d", err);
1425 return;
1426 }
1427 }
1428
Andreas Huber971305d2010-07-07 13:35:27 -07001429 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
1430
Andreas Huber27366fc2009-11-20 09:32:46 -08001431 if (mFlags & FIRST_FRAME) {
1432 mFlags &= ~FIRST_FRAME;
pmehendale28f939d2011-01-06 14:43:49 -08001433 mSinceLastDropped = 0;
Andreas Huber971305d2010-07-07 13:35:27 -07001434 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
Andreas Huber27366fc2009-11-20 09:32:46 -08001435 }
1436
1437 int64_t realTimeUs, mediaTimeUs;
Andreas Huber971305d2010-07-07 13:35:27 -07001438 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
Andreas Huber27366fc2009-11-20 09:32:46 -08001439 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1440 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1441 }
1442
Andreas Hubera2c29972011-02-24 12:05:40 -08001443 if (wasSeeking == SEEK_VIDEO_ONLY) {
1444 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1445
1446 int64_t latenessUs = nowUs - timeUs;
1447
1448 if (latenessUs > 0) {
1449 LOGI("after SEEK_VIDEO_ONLY we're late by %.2f secs", latenessUs / 1E6);
1450 }
1451 }
1452
1453 if (wasSeeking == NO_SEEK) {
Andreas Huber614d22c2010-10-29 15:47:52 -07001454 // Let's display the first frame after seeking right away.
Andreas Huberf88f8442010-08-10 11:18:36 -07001455
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001456 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
Andreas Huber27366fc2009-11-20 09:32:46 -08001457
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001458 int64_t latenessUs = nowUs - timeUs;
1459
Andreas Hubera2c29972011-02-24 12:05:40 -08001460 if (latenessUs > 500000ll
1461 && mRTSPController == NULL
1462 && mAudioPlayer != NULL
1463 && mAudioPlayer->getMediaTimeMapping(
1464 &realTimeUs, &mediaTimeUs)) {
1465 LOGI("we're much too late (%.2f secs), video skipping ahead",
1466 latenessUs / 1E6);
1467
1468 mVideoBuffer->release();
1469 mVideoBuffer = NULL;
1470
1471 mSeeking = SEEK_VIDEO_ONLY;
1472 mSeekTimeUs = mediaTimeUs;
1473
1474 postVideoEvent_l();
1475 return;
1476 }
1477
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001478 if (latenessUs > 40000) {
1479 // We're more than 40ms late.
1480 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
1481 if ( mSinceLastDropped > FRAME_DROP_FREQ)
1482 {
1483 LOGV("we're late by %lld us (%.2f secs) dropping one after %d frames", latenessUs, latenessUs / 1E6, mSinceLastDropped);
1484 mSinceLastDropped = 0;
1485 mVideoBuffer->release();
1486 mVideoBuffer = NULL;
1487
1488 postVideoEvent_l();
1489 return;
1490 }
1491 }
1492
1493 if (latenessUs < -10000) {
1494 // We're more than 10ms early.
1495
1496 postVideoEvent_l(10000);
pmehendale28f939d2011-01-06 14:43:49 -08001497 return;
1498 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001499 }
1500
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001501 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
1502 mVideoRendererIsPreview = false;
1503
Andreas Huber7085b6842010-02-03 16:02:02 -08001504 initRenderer_l();
1505 }
1506
1507 if (mVideoRenderer != NULL) {
pmehendale28f939d2011-01-06 14:43:49 -08001508 mSinceLastDropped++;
Andreas Huber7085b6842010-02-03 16:02:02 -08001509 mVideoRenderer->render(mVideoBuffer);
1510 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001511
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001512 mVideoBuffer->release();
Andreas Huber27366fc2009-11-20 09:32:46 -08001513 mVideoBuffer = NULL;
1514
Andreas Hubera2c29972011-02-24 12:05:40 -08001515 if (wasSeeking != NO_SEEK && (mFlags & SEEK_PREVIEW)) {
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001516 mFlags &= ~SEEK_PREVIEW;
1517 return;
1518 }
1519
Andreas Huber27366fc2009-11-20 09:32:46 -08001520 postVideoEvent_l();
1521}
1522
1523void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
1524 if (mVideoEventPending) {
1525 return;
1526 }
1527
1528 mVideoEventPending = true;
1529 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1530}
1531
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001532void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001533 if (mStreamDoneEventPending) {
1534 return;
1535 }
1536 mStreamDoneEventPending = true;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001537
1538 mStreamDoneStatus = status;
Andreas Huber27366fc2009-11-20 09:32:46 -08001539 mQueue.postEvent(mStreamDoneEvent);
1540}
1541
Andreas Huberb9e63832010-01-26 16:20:10 -08001542void AwesomePlayer::postBufferingEvent_l() {
Andreas Huberb9e63832010-01-26 16:20:10 -08001543 if (mBufferingEventPending) {
1544 return;
1545 }
1546 mBufferingEventPending = true;
1547 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1548}
1549
Andreas Huber52c78322011-01-11 15:05:28 -08001550void AwesomePlayer::postVideoLagEvent_l() {
1551 if (mVideoLagEventPending) {
1552 return;
1553 }
1554 mVideoLagEventPending = true;
1555 mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
1556}
1557
Andreas Huber70d10c02010-02-03 11:37:29 -08001558void AwesomePlayer::postCheckAudioStatusEvent_l() {
1559 if (mAudioStatusEventPending) {
1560 return;
1561 }
1562 mAudioStatusEventPending = true;
Andreas Huber2b359ed2010-09-28 11:56:39 -07001563 mQueue.postEvent(mCheckAudioStatusEvent);
Andreas Huber70d10c02010-02-03 11:37:29 -08001564}
1565
1566void AwesomePlayer::onCheckAudioStatus() {
1567 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -08001568 if (!mAudioStatusEventPending) {
1569 // Event was dispatched and while we were blocking on the mutex,
1570 // has already been cancelled.
1571 return;
1572 }
1573
Andreas Huber70d10c02010-02-03 11:37:29 -08001574 mAudioStatusEventPending = false;
1575
1576 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1577 mWatchForAudioSeekComplete = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001578
1579 if (!mSeekNotificationSent) {
1580 notifyListener_l(MEDIA_SEEK_COMPLETE);
1581 mSeekNotificationSent = true;
1582 }
Andreas Huberddb709c2010-04-07 10:24:35 -07001583
Andreas Hubera2c29972011-02-24 12:05:40 -08001584 mSeeking = NO_SEEK;
Andreas Huber70d10c02010-02-03 11:37:29 -08001585 }
1586
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001587 status_t finalStatus;
1588 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
Andreas Huber70d10c02010-02-03 11:37:29 -08001589 mWatchForAudioEOS = false;
Andreas Huber971305d2010-07-07 13:35:27 -07001590 mFlags |= AUDIO_AT_EOS;
1591 mFlags |= FIRST_FRAME;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001592 postStreamDoneEvent_l(finalStatus);
Andreas Huber70d10c02010-02-03 11:37:29 -08001593 }
Andreas Huber70d10c02010-02-03 11:37:29 -08001594}
1595
Andreas Huber6be780e2010-02-08 14:40:30 -08001596status_t AwesomePlayer::prepare() {
1597 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001598 return prepare_l();
1599}
Andreas Huber6be780e2010-02-08 14:40:30 -08001600
Andreas Huberffdf4782010-02-09 14:05:43 -08001601status_t AwesomePlayer::prepare_l() {
1602 if (mFlags & PREPARED) {
1603 return OK;
1604 }
1605
1606 if (mFlags & PREPARING) {
1607 return UNKNOWN_ERROR;
1608 }
1609
1610 mIsAsyncPrepare = false;
Andreas Huber6be780e2010-02-08 14:40:30 -08001611 status_t err = prepareAsync_l();
1612
1613 if (err != OK) {
1614 return err;
1615 }
1616
Andreas Huberffdf4782010-02-09 14:05:43 -08001617 while (mFlags & PREPARING) {
Andreas Huber6be780e2010-02-08 14:40:30 -08001618 mPreparedCondition.wait(mLock);
1619 }
1620
Andreas Huberffdf4782010-02-09 14:05:43 -08001621 return mPrepareResult;
Andreas Huber6be780e2010-02-08 14:40:30 -08001622}
1623
1624status_t AwesomePlayer::prepareAsync() {
1625 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001626
1627 if (mFlags & PREPARING) {
1628 return UNKNOWN_ERROR; // async prepare already pending
1629 }
1630
1631 mIsAsyncPrepare = true;
Andreas Huber6be780e2010-02-08 14:40:30 -08001632 return prepareAsync_l();
1633}
1634
1635status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001636 if (mFlags & PREPARING) {
1637 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huber6be780e2010-02-08 14:40:30 -08001638 }
1639
Andreas Huber406a18b2010-02-18 16:45:13 -08001640 if (!mQueueStarted) {
1641 mQueue.start();
1642 mQueueStarted = true;
1643 }
1644
Andreas Huberffdf4782010-02-09 14:05:43 -08001645 mFlags |= PREPARING;
Andreas Huber6be780e2010-02-08 14:40:30 -08001646 mAsyncPrepareEvent = new AwesomeEvent(
1647 this, &AwesomePlayer::onPrepareAsyncEvent);
1648
1649 mQueue.postEvent(mAsyncPrepareEvent);
1650
1651 return OK;
1652}
1653
Andreas Huberffdf4782010-02-09 14:05:43 -08001654status_t AwesomePlayer::finishSetDataSource_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001655 sp<DataSource> dataSource;
1656
Andreas Huber118a1502011-02-17 13:35:08 -08001657 if (!strncasecmp("http://", mUri.string(), 7)
1658 || !strncasecmp("https://", mUri.string(), 8)) {
Andreas Huber53182c42011-02-24 14:42:48 -08001659 mConnectingDataSource = new NuHTTPDataSource(
1660 (mFlags & INCOGNITO) ? NuHTTPDataSource::kFlagIncognito : 0);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001661
1662 mLock.unlock();
Andreas Huber3a53dc52010-06-11 09:57:46 -07001663 status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001664 mLock.lock();
1665
1666 if (err != OK) {
1667 mConnectingDataSource.clear();
1668
1669 LOGI("mConnectingDataSource->connect() returned %d", err);
1670 return err;
1671 }
1672
Andreas Huber4d61f602010-06-10 11:17:50 -07001673#if 0
1674 mCachedSource = new NuCachedSource2(
1675 new ThrottledSource(
1676 mConnectingDataSource, 50 * 1024 /* bytes/sec */));
1677#else
1678 mCachedSource = new NuCachedSource2(mConnectingDataSource);
1679#endif
Andreas Huberedbb4d82010-03-12 08:59:22 -08001680 mConnectingDataSource.clear();
Andreas Huber4d61f602010-06-10 11:17:50 -07001681
1682 dataSource = mCachedSource;
Andreas Huber96346652011-01-19 15:07:19 -08001683
1684 // We're going to prefill the cache before trying to instantiate
1685 // the extractor below, as the latter is an operation that otherwise
1686 // could block on the datasource for a significant amount of time.
1687 // During that time we'd be unable to abort the preparation phase
1688 // without this prefill.
1689
1690 mLock.unlock();
1691
1692 for (;;) {
1693 status_t finalStatus;
1694 size_t cachedDataRemaining =
1695 mCachedSource->approxDataRemaining(&finalStatus);
1696
1697 if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
1698 || (mFlags & PREPARE_CANCELLED)) {
1699 break;
1700 }
1701
1702 usleep(200000);
1703 }
1704
1705 mLock.lock();
1706
1707 if (mFlags & PREPARE_CANCELLED) {
1708 LOGI("Prepare cancelled while waiting for initial cache fill.");
1709 return UNKNOWN_ERROR;
1710 }
Andreas Huber7a747b82010-06-07 15:19:40 -07001711 } else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
1712 if (mLooper == NULL) {
1713 mLooper = new ALooper;
Andreas Huberc4e0b702010-08-27 15:21:07 -07001714 mLooper->setName("rtsp");
Andreas Huber7a747b82010-06-07 15:19:40 -07001715 mLooper->start();
1716 }
1717 mRTSPController = new ARTSPController(mLooper);
Andreas Hubercb218792011-02-14 14:14:23 -08001718 mConnectingRTSPController = mRTSPController;
1719
1720 mLock.unlock();
Andreas Huber7a747b82010-06-07 15:19:40 -07001721 status_t err = mRTSPController->connect(mUri.string());
Andreas Hubercb218792011-02-14 14:14:23 -08001722 mLock.lock();
1723
1724 mConnectingRTSPController.clear();
Andreas Huber202348e2010-06-07 14:35:29 -07001725
Andreas Huber7a747b82010-06-07 15:19:40 -07001726 LOGI("ARTSPController::connect returned %d", err);
1727
1728 if (err != OK) {
1729 mRTSPController.clear();
1730 return err;
1731 }
1732
1733 sp<MediaExtractor> extractor = mRTSPController.get();
Andreas Huber202348e2010-06-07 14:35:29 -07001734 return setDataSource_l(extractor);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001735 } else {
1736 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1737 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001738
1739 if (dataSource == NULL) {
1740 return UNKNOWN_ERROR;
1741 }
1742
1743 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1744
1745 if (extractor == NULL) {
1746 return UNKNOWN_ERROR;
1747 }
1748
Gloria Wangd5770912010-06-22 13:55:38 -07001749 dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
Gloria Wangc2c22e72010-11-01 15:53:16 -07001750 if (mDecryptHandle != NULL) {
Gloria Wangadc4d9c2011-02-08 13:24:08 -08001751 CHECK(mDrmManagerClient);
James Dong3be15932011-03-25 08:41:57 -07001752 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
Gloria Wangc2c22e72010-11-01 15:53:16 -07001753 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
1754 }
Gloria Wangd5770912010-06-22 13:55:38 -07001755 }
1756
Andreas Huberffdf4782010-02-09 14:05:43 -08001757 return setDataSource_l(extractor);
1758}
1759
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001760void AwesomePlayer::abortPrepare(status_t err) {
1761 CHECK(err != OK);
1762
1763 if (mIsAsyncPrepare) {
1764 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1765 }
1766
1767 mPrepareResult = err;
Andreas Hubereaf2c5a2010-10-19 12:18:51 -07001768 mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001769 mAsyncPrepareEvent = NULL;
1770 mPreparedCondition.broadcast();
1771}
1772
Andreas Huberf71daba2010-03-24 09:24:40 -07001773// static
1774bool AwesomePlayer::ContinuePreparation(void *cookie) {
1775 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
1776
1777 return (me->mFlags & PREPARE_CANCELLED) == 0;
1778}
1779
Andreas Huber6be780e2010-02-08 14:40:30 -08001780void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001781 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001782
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001783 if (mFlags & PREPARE_CANCELLED) {
1784 LOGI("prepare was cancelled before doing anything");
1785 abortPrepare(UNKNOWN_ERROR);
1786 return;
1787 }
1788
1789 if (mUri.size() > 0) {
1790 status_t err = finishSetDataSource_l();
1791
1792 if (err != OK) {
1793 abortPrepare(err);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001794 return;
1795 }
Andreas Huber6be780e2010-02-08 14:40:30 -08001796 }
1797
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001798 if (mVideoTrack != NULL && mVideoSource == NULL) {
1799 status_t err = initVideoDecoder();
Andreas Huber6be780e2010-02-08 14:40:30 -08001800
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001801 if (err != OK) {
1802 abortPrepare(err);
1803 return;
1804 }
1805 }
1806
1807 if (mAudioTrack != NULL && mAudioSource == NULL) {
1808 status_t err = initAudioDecoder();
1809
1810 if (err != OK) {
1811 abortPrepare(err);
1812 return;
1813 }
1814 }
1815
Andreas Hubereaf2c5a2010-10-19 12:18:51 -07001816 mFlags |= PREPARING_CONNECTED;
1817
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001818 if (mCachedSource != NULL || mRTSPController != NULL) {
1819 postBufferingEvent_l();
1820 } else {
1821 finishAsyncPrepare_l();
1822 }
1823}
1824
1825void AwesomePlayer::finishAsyncPrepare_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001826 if (mIsAsyncPrepare) {
Andreas Hubere3c01832010-08-16 08:49:37 -07001827 if (mVideoSource == NULL) {
Andreas Huberffdf4782010-02-09 14:05:43 -08001828 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1829 } else {
Andreas Hubere3c01832010-08-16 08:49:37 -07001830 notifyVideoSize_l();
Andreas Huberffdf4782010-02-09 14:05:43 -08001831 }
1832
1833 notifyListener_l(MEDIA_PREPARED);
Andreas Huber6be780e2010-02-08 14:40:30 -08001834 }
1835
Andreas Huberffdf4782010-02-09 14:05:43 -08001836 mPrepareResult = OK;
Andreas Hubereaf2c5a2010-10-19 12:18:51 -07001837 mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
Andreas Huberffdf4782010-02-09 14:05:43 -08001838 mFlags |= PREPARED;
Andreas Huber6be780e2010-02-08 14:40:30 -08001839 mAsyncPrepareEvent = NULL;
Andreas Huberffdf4782010-02-09 14:05:43 -08001840 mPreparedCondition.broadcast();
Andreas Huber6be780e2010-02-08 14:40:30 -08001841}
1842
Andreas Huber62f7ffe2010-05-06 10:18:05 -07001843uint32_t AwesomePlayer::flags() const {
1844 return mExtractorFlags;
1845}
1846
Andreas Huber2b359ed2010-09-28 11:56:39 -07001847void AwesomePlayer::postAudioEOS() {
1848 postCheckAudioStatusEvent_l();
1849}
1850
1851void AwesomePlayer::postAudioSeekComplete() {
1852 postCheckAudioStatusEvent_l();
1853}
1854
Andreas Huber27366fc2009-11-20 09:32:46 -08001855} // namespace android