blob: 8866750ff4f8b9472da7c96a46c743097d730c18 [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
17//#define LOG_NDEBUG 0
18#define LOG_TAG "AwesomePlayer"
19#include <utils/Log.h>
20
Andreas Huber4ab5a6f2010-02-11 11:00:26 -080021#include <dlfcn.h>
22
Andreas Huber7a747b82010-06-07 15:19:40 -070023#include "include/ARTSPController.h"
Andreas Huber27366fc2009-11-20 09:32:46 -080024#include "include/AwesomePlayer.h"
Andreas Huber1314e732009-12-14 14:18:22 -080025#include "include/SoftwareRenderer.h"
Andreas Huber4d61f602010-06-10 11:17:50 -070026#include "include/NuCachedSource2.h"
27#include "include/ThrottledSource.h"
Andreas Huber54d09722010-10-12 11:34:37 -070028#include "include/MPEG2TSExtractor.h"
Andreas Huber27366fc2009-11-20 09:32:46 -080029
Andreas Hubera67d5382009-12-10 15:32:12 -080030#include <binder/IPCThreadState.h>
Andreas Huber52b52cd2010-11-23 11:41:34 -080031#include <media/stagefright/foundation/hexdump.h>
32#include <media/stagefright/foundation/ADebug.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080033#include <media/stagefright/AudioPlayer.h>
34#include <media/stagefright/DataSource.h>
35#include <media/stagefright/FileSource.h>
36#include <media/stagefright/MediaBuffer.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080037#include <media/stagefright/MediaDefs.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080038#include <media/stagefright/MediaExtractor.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080039#include <media/stagefright/MediaSource.h>
40#include <media/stagefright/MetaData.h>
41#include <media/stagefright/OMXCodec.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080042
Andreas Hubere3c01832010-08-16 08:49:37 -070043#include <surfaceflinger/Surface.h>
Mathias Agopian000479f2010-02-09 17:46:37 -080044
Andreas Huber7a747b82010-06-07 15:19:40 -070045#include <media/stagefright/foundation/ALooper.h>
Andreas Huberae9d5072010-12-06 10:36:06 -080046#include <media/stagefright/foundation/AMessage.h>
Andreas Huber202348e2010-06-07 14:35:29 -070047
Andreas Huber6a1f5f92010-11-15 09:03:03 -080048#define USE_SURFACE_ALLOC 1
pmehendale28f939d2011-01-06 14:43:49 -080049#define FRAME_DROP_FREQ 7
Andreas Huber6a1f5f92010-11-15 09:03:03 -080050
Andreas Huber27366fc2009-11-20 09:32:46 -080051namespace android {
52
Andreas Huber87ab9cd2010-09-03 13:20:33 -070053static int64_t kLowWaterMarkUs = 2000000ll; // 2secs
54static int64_t kHighWaterMarkUs = 10000000ll; // 10secs
Andreas Huberb2934b12011-02-08 10:18:41 -080055static int64_t kHighWaterMarkRTSPUs = 4000000ll; // 4secs
Andreas Huber96346652011-01-19 15:07:19 -080056static const size_t kLowWaterMarkBytes = 40000;
57static const size_t kHighWaterMarkBytes = 200000;
Andreas Huber87ab9cd2010-09-03 13:20:33 -070058
Andreas Huber27366fc2009-11-20 09:32:46 -080059struct AwesomeEvent : public TimedEventQueue::Event {
Andreas Huber6be780e2010-02-08 14:40:30 -080060 AwesomeEvent(
61 AwesomePlayer *player,
62 void (AwesomePlayer::*method)())
Andreas Huber27366fc2009-11-20 09:32:46 -080063 : mPlayer(player),
Andreas Huber6be780e2010-02-08 14:40:30 -080064 mMethod(method) {
Andreas Huber27366fc2009-11-20 09:32:46 -080065 }
66
67protected:
68 virtual ~AwesomeEvent() {}
69
70 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
Andreas Huber6be780e2010-02-08 14:40:30 -080071 (mPlayer->*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080072 }
73
74private:
75 AwesomePlayer *mPlayer;
Andreas Huber6be780e2010-02-08 14:40:30 -080076 void (AwesomePlayer::*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080077
78 AwesomeEvent(const AwesomeEvent &);
79 AwesomeEvent &operator=(const AwesomeEvent &);
80};
81
Andreas Huber1314e732009-12-14 14:18:22 -080082struct AwesomeLocalRenderer : public AwesomeRenderer {
83 AwesomeLocalRenderer(
Andreas Huber1bb0ffd2010-11-22 13:06:35 -080084 const sp<Surface> &surface, const sp<MetaData> &meta)
85 : mTarget(new SoftwareRenderer(surface, meta)) {
Andreas Huber1314e732009-12-14 14:18:22 -080086 }
87
88 virtual void render(MediaBuffer *buffer) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -080089 render((const uint8_t *)buffer->data() + buffer->range_offset(),
90 buffer->range_length());
91 }
92
93 void render(const void *data, size_t size) {
94 mTarget->render(data, size, NULL);
Andreas Huber1314e732009-12-14 14:18:22 -080095 }
96
97protected:
98 virtual ~AwesomeLocalRenderer() {
99 delete mTarget;
100 mTarget = NULL;
101 }
102
103private:
Andreas Huberc23dabf2010-11-16 13:05:53 -0800104 SoftwareRenderer *mTarget;
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800105
Andreas Huber1314e732009-12-14 14:18:22 -0800106 AwesomeLocalRenderer(const AwesomeLocalRenderer &);
107 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
108};
109
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700110struct AwesomeNativeWindowRenderer : public AwesomeRenderer {
Andreas Huber940c8662010-11-16 15:26:30 -0800111 AwesomeNativeWindowRenderer(
112 const sp<ANativeWindow> &nativeWindow,
113 int32_t rotationDegrees)
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700114 : mNativeWindow(nativeWindow) {
Andreas Huber940c8662010-11-16 15:26:30 -0800115 applyRotation(rotationDegrees);
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700116 }
117
118 virtual void render(MediaBuffer *buffer) {
119 status_t err = mNativeWindow->queueBuffer(
120 mNativeWindow.get(), buffer->graphicBuffer().get());
121 if (err != 0) {
122 LOGE("queueBuffer failed with error %s (%d)", strerror(-err),
123 -err);
124 return;
125 }
126
127 sp<MetaData> metaData = buffer->meta_data();
128 metaData->setInt32(kKeyRendered, 1);
129 }
130
131protected:
132 virtual ~AwesomeNativeWindowRenderer() {}
133
134private:
135 sp<ANativeWindow> mNativeWindow;
136
Andreas Huber940c8662010-11-16 15:26:30 -0800137 void applyRotation(int32_t rotationDegrees) {
138 uint32_t transform;
139 switch (rotationDegrees) {
140 case 0: transform = 0; break;
141 case 90: transform = HAL_TRANSFORM_ROT_90; break;
142 case 180: transform = HAL_TRANSFORM_ROT_180; break;
143 case 270: transform = HAL_TRANSFORM_ROT_270; break;
144 default: transform = 0; break;
145 }
146
147 if (transform) {
148 CHECK_EQ(0, native_window_set_buffers_transform(
149 mNativeWindow.get(), transform));
150 }
151 }
152
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700153 AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &);
154 AwesomeNativeWindowRenderer &operator=(
155 const AwesomeNativeWindowRenderer &);
156};
157
Andreas Huber52b52cd2010-11-23 11:41:34 -0800158////////////////////////////////////////////////////////////////////////////////
159
Andreas Huber27366fc2009-11-20 09:32:46 -0800160AwesomePlayer::AwesomePlayer()
Andreas Huber406a18b2010-02-18 16:45:13 -0800161 : mQueueStarted(false),
162 mTimeSource(NULL),
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800163 mVideoRendererIsPreview(false),
Andreas Huber27366fc2009-11-20 09:32:46 -0800164 mAudioPlayer(NULL),
James Dong08adfd22011-01-16 11:30:13 -0800165 mDisplayWidth(0),
166 mDisplayHeight(0),
Andreas Huberffdf4782010-02-09 14:05:43 -0800167 mFlags(0),
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700168 mExtractorFlags(0),
Andreas Huberba7ec912010-02-12 10:42:02 -0800169 mVideoBuffer(NULL),
Gloria Wangd5770912010-06-22 13:55:38 -0700170 mDecryptHandle(NULL) {
Andreas Huber52b52cd2010-11-23 11:41:34 -0800171 CHECK_EQ(mClient.connect(), (status_t)OK);
Andreas Huber27366fc2009-11-20 09:32:46 -0800172
173 DataSource::RegisterDefaultSniffers();
174
Andreas Huber6be780e2010-02-08 14:40:30 -0800175 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
Andreas Huber27366fc2009-11-20 09:32:46 -0800176 mVideoEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800177 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
Andreas Huber27366fc2009-11-20 09:32:46 -0800178 mStreamDoneEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800179 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
Andreas Huberb9e63832010-01-26 16:20:10 -0800180 mBufferingEventPending = false;
Andreas Huber52c78322011-01-11 15:05:28 -0800181 mVideoLagEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoLagUpdate);
182 mVideoEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800183
184 mCheckAudioStatusEvent = new AwesomeEvent(
185 this, &AwesomePlayer::onCheckAudioStatus);
186
Andreas Huber70d10c02010-02-03 11:37:29 -0800187 mAudioStatusEventPending = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800188
Andreas Huber27366fc2009-11-20 09:32:46 -0800189 reset();
190}
191
192AwesomePlayer::~AwesomePlayer() {
Andreas Huber406a18b2010-02-18 16:45:13 -0800193 if (mQueueStarted) {
194 mQueue.stop();
195 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800196
197 reset();
198
199 mClient.disconnect();
200}
201
Andreas Huberb9e63832010-01-26 16:20:10 -0800202void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800203 mQueue.cancelEvent(mVideoEvent->eventID());
204 mVideoEventPending = false;
205 mQueue.cancelEvent(mStreamDoneEvent->eventID());
206 mStreamDoneEventPending = false;
Andreas Huber70d10c02010-02-03 11:37:29 -0800207 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
208 mAudioStatusEventPending = false;
Andreas Huber52c78322011-01-11 15:05:28 -0800209 mQueue.cancelEvent(mVideoLagEvent->eventID());
210 mVideoLagEventPending = false;
Andreas Huberb9e63832010-01-26 16:20:10 -0800211
212 if (!keepBufferingGoing) {
213 mQueue.cancelEvent(mBufferingEvent->eventID());
214 mBufferingEventPending = false;
215 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800216}
217
Andreas Hubera3f43842010-01-21 10:28:45 -0800218void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800219 Mutex::Autolock autoLock(mLock);
220 mListener = listener;
221}
222
Andreas Huber433c9ac2010-01-27 16:49:05 -0800223status_t AwesomePlayer::setDataSource(
224 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800225 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800226 return setDataSource_l(uri, headers);
227}
Andreas Huber27366fc2009-11-20 09:32:46 -0800228
Andreas Huberba7ec912010-02-12 10:42:02 -0800229status_t AwesomePlayer::setDataSource_l(
230 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800231 reset_l();
232
Andreas Huberffdf4782010-02-09 14:05:43 -0800233 mUri = uri;
Andreas Huberb9e63832010-01-26 16:20:10 -0800234
Andreas Huberffdf4782010-02-09 14:05:43 -0800235 if (headers) {
236 mUriHeaders = *headers;
Andreas Huberb9e63832010-01-26 16:20:10 -0800237 }
238
Andreas Huberffdf4782010-02-09 14:05:43 -0800239 // The actual work will be done during preparation in the call to
240 // ::finishSetDataSource_l to avoid blocking the calling thread in
241 // setDataSource for any significant time.
Andreas Huber27366fc2009-11-20 09:32:46 -0800242
Andreas Huberffdf4782010-02-09 14:05:43 -0800243 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800244}
245
246status_t AwesomePlayer::setDataSource(
247 int fd, int64_t offset, int64_t length) {
248 Mutex::Autolock autoLock(mLock);
249
250 reset_l();
251
Andreas Huberba7ec912010-02-12 10:42:02 -0800252 sp<DataSource> dataSource = new FileSource(fd, offset, length);
Andreas Huber27366fc2009-11-20 09:32:46 -0800253
Andreas Huberba7ec912010-02-12 10:42:02 -0800254 status_t err = dataSource->initCheck();
Andreas Huber27366fc2009-11-20 09:32:46 -0800255
256 if (err != OK) {
257 return err;
258 }
259
Andreas Huberba7ec912010-02-12 10:42:02 -0800260 mFileSource = dataSource;
261
262 return setDataSource_l(dataSource);
263}
264
Andreas Huber52b52cd2010-11-23 11:41:34 -0800265status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) {
Andreas Huberd9367262010-12-16 10:16:36 -0800266 return INVALID_OPERATION;
Andreas Huber52b52cd2010-11-23 11:41:34 -0800267}
268
Andreas Huberba7ec912010-02-12 10:42:02 -0800269status_t AwesomePlayer::setDataSource_l(
270 const sp<DataSource> &dataSource) {
271 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
Andreas Huber27366fc2009-11-20 09:32:46 -0800272
273 if (extractor == NULL) {
274 return UNKNOWN_ERROR;
275 }
276
Gloria Wangd5770912010-06-22 13:55:38 -0700277 dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
Gloria Wangadc4d9c2011-02-08 13:24:08 -0800278 if (mDecryptHandle != NULL) {
279 CHECK(mDrmManagerClient);
280 if (RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
281 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
282 }
Gloria Wangd5770912010-06-22 13:55:38 -0700283 }
284
Andreas Huber27366fc2009-11-20 09:32:46 -0800285 return setDataSource_l(extractor);
286}
287
288status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700289 // Attempt to approximate overall stream bitrate by summing all
290 // tracks' individual bitrates, if not all of them advertise bitrate,
291 // we have to fail.
292
293 int64_t totalBitRate = 0;
294
295 for (size_t i = 0; i < extractor->countTracks(); ++i) {
296 sp<MetaData> meta = extractor->getTrackMetaData(i);
297
298 int32_t bitrate;
299 if (!meta->findInt32(kKeyBitRate, &bitrate)) {
300 totalBitRate = -1;
301 break;
302 }
303
304 totalBitRate += bitrate;
305 }
306
307 mBitrate = totalBitRate;
308
309 LOGV("mBitrate = %lld bits/sec", mBitrate);
310
Andreas Huber27366fc2009-11-20 09:32:46 -0800311 bool haveAudio = false;
312 bool haveVideo = false;
313 for (size_t i = 0; i < extractor->countTracks(); ++i) {
314 sp<MetaData> meta = extractor->getTrackMetaData(i);
315
316 const char *mime;
317 CHECK(meta->findCString(kKeyMIMEType, &mime));
318
319 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800320 setVideoSource(extractor->getTrack(i));
321 haveVideo = true;
James Dong08adfd22011-01-16 11:30:13 -0800322
323 // Set the presentation/display size
324 int32_t displayWidth, displayHeight;
325 bool success = meta->findInt32(kKeyDisplayWidth, &displayWidth);
326 if (success) {
327 success = meta->findInt32(kKeyDisplayHeight, &displayHeight);
328 }
329 if (success) {
330 mDisplayWidth = displayWidth;
331 mDisplayHeight = displayHeight;
332 }
333
Andreas Huber27366fc2009-11-20 09:32:46 -0800334 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800335 setAudioSource(extractor->getTrack(i));
336 haveAudio = true;
Andreas Huber9fee0b22010-09-03 14:09:21 -0700337
Andreas Huber1913c1a2010-10-04 11:09:31 -0700338 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
339 // Only do this for vorbis audio, none of the other audio
340 // formats even support this ringtone specific hack and
341 // retrieving the metadata on some extractors may turn out
342 // to be very expensive.
343 sp<MetaData> fileMeta = extractor->getMetaData();
344 int32_t loop;
345 if (fileMeta != NULL
346 && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
347 mFlags |= AUTO_LOOPING;
348 }
Andreas Huber9fee0b22010-09-03 14:09:21 -0700349 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800350 }
351
352 if (haveAudio && haveVideo) {
353 break;
354 }
355 }
356
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700357 if (!haveAudio && !haveVideo) {
358 return UNKNOWN_ERROR;
359 }
360
361 mExtractorFlags = extractor->flags();
362
363 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800364}
365
366void AwesomePlayer::reset() {
367 Mutex::Autolock autoLock(mLock);
368 reset_l();
369}
370
371void AwesomePlayer::reset_l() {
James Dong08adfd22011-01-16 11:30:13 -0800372 mDisplayWidth = 0;
373 mDisplayHeight = 0;
Andreas Huber90c65652011-01-04 10:19:13 -0800374
Gloria Wangd5770912010-06-22 13:55:38 -0700375 if (mDecryptHandle != NULL) {
376 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
377 Playback::STOP, 0);
Gloria Wangd5770912010-06-22 13:55:38 -0700378 mDecryptHandle = NULL;
379 mDrmManagerClient = NULL;
380 }
381
Andreas Huberedbb4d82010-03-12 08:59:22 -0800382 if (mFlags & PREPARING) {
383 mFlags |= PREPARE_CANCELLED;
384 if (mConnectingDataSource != NULL) {
385 LOGI("interrupting the connection process");
386 mConnectingDataSource->disconnect();
Andreas Hubercb218792011-02-14 14:14:23 -0800387 } else if (mConnectingRTSPController != NULL) {
388 LOGI("interrupting the connection process");
389 mConnectingRTSPController->disconnect();
Andreas Huberedbb4d82010-03-12 08:59:22 -0800390 }
Andreas Hubereaf2c5a2010-10-19 12:18:51 -0700391
392 if (mFlags & PREPARING_CONNECTED) {
393 // We are basically done preparing, we're just buffering
394 // enough data to start playback, we can safely interrupt that.
395 finishAsyncPrepare_l();
396 }
Andreas Huberedbb4d82010-03-12 08:59:22 -0800397 }
398
Andreas Huberffdf4782010-02-09 14:05:43 -0800399 while (mFlags & PREPARING) {
400 mPreparedCondition.wait(mLock);
401 }
402
Andreas Huber27366fc2009-11-20 09:32:46 -0800403 cancelPlayerEvents();
404
Andreas Huber4d61f602010-06-10 11:17:50 -0700405 mCachedSource.clear();
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800406 mAudioTrack.clear();
407 mVideoTrack.clear();
408
Andreas Huberba7ec912010-02-12 10:42:02 -0800409 // Shutdown audio first, so that the respone to the reset request
410 // appears to happen instantaneously as far as the user is concerned
411 // If we did this later, audio would continue playing while we
412 // shutdown the video-related resources and the player appear to
413 // not be as responsive to a reset request.
Andreas Huberedbb4d82010-03-12 08:59:22 -0800414 if (mAudioPlayer == NULL && mAudioSource != NULL) {
415 // If we had an audio player, it would have effectively
416 // taken possession of the audio source and stopped it when
417 // _it_ is stopped. Otherwise this is still our responsibility.
418 mAudioSource->stop();
419 }
Andreas Huberba7ec912010-02-12 10:42:02 -0800420 mAudioSource.clear();
421
Andreas Huberba7ec912010-02-12 10:42:02 -0800422 mTimeSource = NULL;
423
424 delete mAudioPlayer;
425 mAudioPlayer = NULL;
426
Andreas Huber3522b5a52010-01-22 14:36:53 -0800427 mVideoRenderer.clear();
428
Andreas Huber27366fc2009-11-20 09:32:46 -0800429 if (mVideoBuffer) {
430 mVideoBuffer->release();
431 mVideoBuffer = NULL;
432 }
433
Andreas Hubere0dd7d32010-08-24 14:33:58 -0700434 if (mRTSPController != NULL) {
435 mRTSPController->disconnect();
436 mRTSPController.clear();
437 }
438
Andreas Huber27366fc2009-11-20 09:32:46 -0800439 if (mVideoSource != NULL) {
440 mVideoSource->stop();
Andreas Huber98b48de2010-01-29 10:10:22 -0800441
442 // The following hack is necessary to ensure that the OMX
443 // component is completely released by the time we may try
444 // to instantiate it again.
445 wp<MediaSource> tmp = mVideoSource;
Andreas Huber27366fc2009-11-20 09:32:46 -0800446 mVideoSource.clear();
Andreas Huber98b48de2010-01-29 10:10:22 -0800447 while (tmp.promote() != NULL) {
448 usleep(1000);
449 }
450 IPCThreadState::self()->flushCommands();
Andreas Huber27366fc2009-11-20 09:32:46 -0800451 }
452
Andreas Huber27366fc2009-11-20 09:32:46 -0800453 mDurationUs = -1;
454 mFlags = 0;
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700455 mExtractorFlags = 0;
Andreas Huber27366fc2009-11-20 09:32:46 -0800456 mTimeSourceDeltaUs = 0;
457 mVideoTimeUs = 0;
458
459 mSeeking = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700460 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800461 mSeekTimeUs = 0;
Andreas Huberb9e63832010-01-26 16:20:10 -0800462
Andreas Huberffdf4782010-02-09 14:05:43 -0800463 mUri.setTo("");
464 mUriHeaders.clear();
Andreas Huberba7ec912010-02-12 10:42:02 -0800465
466 mFileSource.clear();
467
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700468 mBitrate = -1;
Andreas Huber27366fc2009-11-20 09:32:46 -0800469}
470
Andreas Huber6be780e2010-02-08 14:40:30 -0800471void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
Andreas Hubera3f43842010-01-21 10:28:45 -0800472 if (mListener != NULL) {
473 sp<MediaPlayerBase> listener = mListener.promote();
474
475 if (listener != NULL) {
Andreas Huber6be780e2010-02-08 14:40:30 -0800476 listener->sendEvent(msg, ext1, ext2);
Andreas Hubera3f43842010-01-21 10:28:45 -0800477 }
478 }
479}
480
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700481bool AwesomePlayer::getBitrate(int64_t *bitrate) {
James Dongb1262a82010-11-16 14:04:54 -0800482 off64_t size;
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700483 if (mDurationUs >= 0 && mCachedSource != NULL
484 && mCachedSource->getSize(&size) == OK) {
485 *bitrate = size * 8000000ll / mDurationUs; // in bits/sec
486 return true;
487 }
488
489 if (mBitrate >= 0) {
490 *bitrate = mBitrate;
491 return true;
492 }
493
494 *bitrate = 0;
495
496 return false;
497}
498
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700499// Returns true iff cached duration is available/applicable.
500bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700501 int64_t bitrate;
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700502
503 if (mRTSPController != NULL) {
504 *durationUs = mRTSPController->getQueueDurationUs(eos);
505 return true;
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700506 } else if (mCachedSource != NULL && getBitrate(&bitrate)) {
Bryan Mawhinneye26275b2011-01-18 19:12:21 +0000507 status_t finalStatus;
508 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700509 *durationUs = cachedDataRemaining * 8000000ll / bitrate;
Bryan Mawhinneye26275b2011-01-18 19:12:21 +0000510 *eos = (finalStatus != OK);
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700511 return true;
512 }
513
514 return false;
515}
516
Andreas Huber10b920c2010-11-11 15:37:17 -0800517void AwesomePlayer::ensureCacheIsFetching_l() {
518 if (mCachedSource != NULL) {
519 mCachedSource->resumeFetchingIfNecessary();
520 }
521}
522
Andreas Huber52c78322011-01-11 15:05:28 -0800523void AwesomePlayer::onVideoLagUpdate() {
524 Mutex::Autolock autoLock(mLock);
525 if (!mVideoLagEventPending) {
526 return;
527 }
528 mVideoLagEventPending = false;
529
530 int64_t audioTimeUs = mAudioPlayer->getMediaTimeUs();
531 int64_t videoLateByUs = audioTimeUs - mVideoTimeUs;
532
533 if (videoLateByUs > 300000ll) {
534 LOGV("video late by %lld ms.", videoLateByUs / 1000ll);
535
536 notifyListener_l(
537 MEDIA_INFO,
538 MEDIA_INFO_VIDEO_TRACK_LAGGING,
539 videoLateByUs / 1000ll);
540 }
541
542 postVideoLagEvent_l();
543}
544
Andreas Huberb9e63832010-01-26 16:20:10 -0800545void AwesomePlayer::onBufferingUpdate() {
546 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800547 if (!mBufferingEventPending) {
548 return;
549 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800550 mBufferingEventPending = false;
551
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700552 if (mCachedSource != NULL) {
Bryan Mawhinneye26275b2011-01-18 19:12:21 +0000553 status_t finalStatus;
554 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus);
555 bool eos = (finalStatus != OK);
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700556
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700557 if (eos) {
Bryan Mawhinneye26275b2011-01-18 19:12:21 +0000558 if (finalStatus == ERROR_END_OF_STREAM) {
559 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
560 }
Andreas Huber05f67872010-10-04 11:36:39 -0700561 if (mFlags & PREPARING) {
562 LOGV("cache has reached EOS, prepare is done.");
563 finishAsyncPrepare_l();
564 }
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700565 } else {
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700566 int64_t bitrate;
567 if (getBitrate(&bitrate)) {
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700568 size_t cachedSize = mCachedSource->cachedSize();
569 int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
570
571 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
572 if (percentage > 100) {
573 percentage = 100;
574 }
575
576 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
577 } else {
578 // We don't know the bitrate of the stream, use absolute size
579 // limits to maintain the cache.
580
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700581 if ((mFlags & PLAYING) && !eos
582 && (cachedDataRemaining < kLowWaterMarkBytes)) {
583 LOGI("cache is running low (< %d) , pausing.",
584 kLowWaterMarkBytes);
585 mFlags |= CACHE_UNDERRUN;
586 pause_l();
Andreas Huber10b920c2010-11-11 15:37:17 -0800587 ensureCacheIsFetching_l();
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700588 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
589 } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
590 if (mFlags & CACHE_UNDERRUN) {
591 LOGI("cache has filled up (> %d), resuming.",
592 kHighWaterMarkBytes);
593 mFlags &= ~CACHE_UNDERRUN;
594 play_l();
595 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
596 } else if (mFlags & PREPARING) {
597 LOGV("cache has filled up (> %d), prepare is done",
598 kHighWaterMarkBytes);
599 finishAsyncPrepare_l();
600 }
601 }
602 }
603 }
604 }
605
606 int64_t cachedDurationUs;
607 bool eos;
608 if (getCachedDuration_l(&cachedDurationUs, &eos)) {
Andreas Huber10b920c2010-11-11 15:37:17 -0800609 LOGV("cachedDurationUs = %.2f secs, eos=%d",
610 cachedDurationUs / 1E6, eos);
611
Andreas Huberb2934b12011-02-08 10:18:41 -0800612 int64_t highWaterMarkUs =
613 (mRTSPController != NULL) ? kHighWaterMarkRTSPUs : kHighWaterMarkUs;
614
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700615 if ((mFlags & PLAYING) && !eos
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700616 && (cachedDurationUs < kLowWaterMarkUs)) {
617 LOGI("cache is running low (%.2f secs) , pausing.",
618 cachedDurationUs / 1E6);
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700619 mFlags |= CACHE_UNDERRUN;
620 pause_l();
Andreas Huber10b920c2010-11-11 15:37:17 -0800621 ensureCacheIsFetching_l();
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700622 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
Andreas Huberb2934b12011-02-08 10:18:41 -0800623 } else if (eos || cachedDurationUs > highWaterMarkUs) {
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700624 if (mFlags & CACHE_UNDERRUN) {
625 LOGI("cache has filled up (%.2f secs), resuming.",
626 cachedDurationUs / 1E6);
627 mFlags &= ~CACHE_UNDERRUN;
628 play_l();
629 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
630 } else if (mFlags & PREPARING) {
631 LOGV("cache has filled up (%.2f secs), prepare is done",
632 cachedDurationUs / 1E6);
633 finishAsyncPrepare_l();
Andreas Huberc23296e2010-08-25 12:31:48 -0700634 }
Andreas Huberc23296e2010-08-25 12:31:48 -0700635 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800636 }
Andreas Huber4d61f602010-06-10 11:17:50 -0700637
Andreas Huber4d61f602010-06-10 11:17:50 -0700638 postBufferingEvent_l();
Andreas Huberb9e63832010-01-26 16:20:10 -0800639}
640
Andreas Huber27366fc2009-11-20 09:32:46 -0800641void AwesomePlayer::onStreamDone() {
642 // Posted whenever any stream finishes playing.
643
644 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800645 if (!mStreamDoneEventPending) {
646 return;
647 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800648 mStreamDoneEventPending = false;
649
Andreas Huberd6c421f2011-02-16 09:05:38 -0800650 if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
Andreas Huber971305d2010-07-07 13:35:27 -0700651 LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
652
653 notifyListener_l(
654 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
655
Andreas Huberc743f452010-10-05 10:25:34 -0700656 pause_l(true /* at eos */);
Andreas Huber971305d2010-07-07 13:35:27 -0700657
658 mFlags |= AT_EOS;
659 return;
660 }
661
662 const bool allDone =
663 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
664 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
665
666 if (!allDone) {
667 return;
668 }
669
Andreas Huber9fee0b22010-09-03 14:09:21 -0700670 if (mFlags & (LOOPING | AUTO_LOOPING)) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800671 seekTo_l(0);
672
Andreas Huber7085b6842010-02-03 16:02:02 -0800673 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800674 postVideoEvent_l();
675 }
676 } else {
Andreas Huber971305d2010-07-07 13:35:27 -0700677 LOGV("MEDIA_PLAYBACK_COMPLETE");
678 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800679
Andreas Huberc743f452010-10-05 10:25:34 -0700680 pause_l(true /* at eos */);
Andreas Huber406a18b2010-02-18 16:45:13 -0800681
682 mFlags |= AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800683 }
684}
685
686status_t AwesomePlayer::play() {
687 Mutex::Autolock autoLock(mLock);
Andreas Huber4d61f602010-06-10 11:17:50 -0700688
689 mFlags &= ~CACHE_UNDERRUN;
690
Andreas Huberba7ec912010-02-12 10:42:02 -0800691 return play_l();
692}
Andreas Huber27366fc2009-11-20 09:32:46 -0800693
Andreas Huberba7ec912010-02-12 10:42:02 -0800694status_t AwesomePlayer::play_l() {
Andreas Huber0a84f4f2011-02-07 11:43:12 -0800695 mFlags &= ~SEEK_PREVIEW;
696
Andreas Huber27366fc2009-11-20 09:32:46 -0800697 if (mFlags & PLAYING) {
698 return OK;
699 }
700
Andreas Huberffdf4782010-02-09 14:05:43 -0800701 if (!(mFlags & PREPARED)) {
702 status_t err = prepare_l();
703
704 if (err != OK) {
705 return err;
706 }
707 }
708
Andreas Huber27366fc2009-11-20 09:32:46 -0800709 mFlags |= PLAYING;
710 mFlags |= FIRST_FRAME;
711
Andreas Huberc1d5c922009-12-10 15:49:04 -0800712 bool deferredAudioSeek = false;
713
Gloria Wang95dbffb2010-11-04 17:38:39 -0700714 if (mDecryptHandle != NULL) {
715 int64_t position;
716 getPosition(&position);
717 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
718 Playback::START, position / 1000);
719 }
720
Andreas Huber27366fc2009-11-20 09:32:46 -0800721 if (mAudioSource != NULL) {
722 if (mAudioPlayer == NULL) {
723 if (mAudioSink != NULL) {
Andreas Huber2b359ed2010-09-28 11:56:39 -0700724 mAudioPlayer = new AudioPlayer(mAudioSink, this);
Andreas Huber27366fc2009-11-20 09:32:46 -0800725 mAudioPlayer->setSource(mAudioSource);
Andreas Huberdc9927d2010-03-08 15:46:13 -0800726
Andreas Huber27366fc2009-11-20 09:32:46 -0800727 mTimeSource = mAudioPlayer;
728
Andreas Huberc1d5c922009-12-10 15:49:04 -0800729 deferredAudioSeek = true;
Andreas Huber70d10c02010-02-03 11:37:29 -0800730
731 mWatchForAudioSeekComplete = false;
732 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800733 }
Andreas Huberce8a1012011-02-11 13:09:36 -0800734 }
735
736 CHECK(!(mFlags & AUDIO_RUNNING));
737
738 if (mVideoSource == NULL) {
739 status_t err = startAudioPlayer_l();
740
741 if (err != OK) {
742 delete mAudioPlayer;
743 mAudioPlayer = NULL;
744
745 mFlags &= ~(PLAYING | FIRST_FRAME);
746
747 if (mDecryptHandle != NULL) {
748 mDrmManagerClient->setPlaybackStatus(
749 mDecryptHandle, Playback::STOP, 0);
750 }
751
752 return err;
753 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800754 }
755 }
756
757 if (mTimeSource == NULL && mAudioPlayer == NULL) {
Andreas Huber971305d2010-07-07 13:35:27 -0700758 mTimeSource = &mSystemTimeSource;
Andreas Huber27366fc2009-11-20 09:32:46 -0800759 }
760
761 if (mVideoSource != NULL) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800762 // Kick off video playback
763 postVideoEvent_l();
Andreas Huber52c78322011-01-11 15:05:28 -0800764
765 if (mAudioSource != NULL && mVideoSource != NULL) {
766 postVideoLagEvent_l();
767 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800768 }
769
Andreas Huberc1d5c922009-12-10 15:49:04 -0800770 if (deferredAudioSeek) {
771 // If there was a seek request while we were paused
772 // and we're just starting up again, honor the request now.
773 seekAudioIfNecessary_l();
774 }
775
Andreas Huber406a18b2010-02-18 16:45:13 -0800776 if (mFlags & AT_EOS) {
777 // Legacy behaviour, if a stream finishes playing and then
778 // is started again, we play from the start...
779 seekTo_l(0);
780 }
781
Andreas Huber27366fc2009-11-20 09:32:46 -0800782 return OK;
783}
784
Andreas Huberce8a1012011-02-11 13:09:36 -0800785status_t AwesomePlayer::startAudioPlayer_l() {
786 CHECK(!(mFlags & AUDIO_RUNNING));
787
788 if (mAudioSource == NULL || mAudioPlayer == NULL) {
789 return OK;
790 }
791
792 if (!(mFlags & AUDIOPLAYER_STARTED)) {
793 mFlags |= AUDIOPLAYER_STARTED;
794
795 // We've already started the MediaSource in order to enable
796 // the prefetcher to read its data.
797 status_t err = mAudioPlayer->start(
798 true /* sourceAlreadyStarted */);
799
800 if (err != OK) {
801 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
802 return err;
803 }
804 } else {
805 mAudioPlayer->resume();
806 }
807
808 mFlags |= AUDIO_RUNNING;
809
810 mWatchForAudioEOS = true;
811
812 return OK;
813}
814
Andreas Hubere3c01832010-08-16 08:49:37 -0700815void AwesomePlayer::notifyVideoSize_l() {
816 sp<MetaData> meta = mVideoSource->getFormat();
817
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800818 int32_t cropLeft, cropTop, cropRight, cropBottom;
819 if (!meta->findRect(
820 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
821 int32_t width, height;
822 CHECK(meta->findInt32(kKeyWidth, &width));
823 CHECK(meta->findInt32(kKeyHeight, &height));
824
825 cropLeft = cropTop = 0;
826 cropRight = width - 1;
827 cropBottom = height - 1;
828
829 LOGV("got dimensions only %d x %d", width, height);
830 } else {
831 LOGV("got crop rect %d, %d, %d, %d",
832 cropLeft, cropTop, cropRight, cropBottom);
833 }
834
835 int32_t usableWidth = cropRight - cropLeft + 1;
836 int32_t usableHeight = cropBottom - cropTop + 1;
James Dong08adfd22011-01-16 11:30:13 -0800837 if (mDisplayWidth != 0) {
838 usableWidth = mDisplayWidth;
839 }
840 if (mDisplayHeight != 0) {
841 usableHeight = mDisplayHeight;
842 }
Andreas Hubere3c01832010-08-16 08:49:37 -0700843
Andreas Huber940c8662010-11-16 15:26:30 -0800844 int32_t rotationDegrees;
845 if (!mVideoTrack->getFormat()->findInt32(
846 kKeyRotation, &rotationDegrees)) {
847 rotationDegrees = 0;
848 }
849
850 if (rotationDegrees == 90 || rotationDegrees == 270) {
851 notifyListener_l(
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800852 MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
Andreas Huber940c8662010-11-16 15:26:30 -0800853 } else {
854 notifyListener_l(
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800855 MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
Andreas Huber940c8662010-11-16 15:26:30 -0800856 }
Andreas Hubere3c01832010-08-16 08:49:37 -0700857}
858
Andreas Huber27366fc2009-11-20 09:32:46 -0800859void AwesomePlayer::initRenderer_l() {
Andreas Huberc23dabf2010-11-16 13:05:53 -0800860 if (mSurface == NULL) {
861 return;
862 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800863
Andreas Huberc23dabf2010-11-16 13:05:53 -0800864 sp<MetaData> meta = mVideoSource->getFormat();
Andreas Huber27366fc2009-11-20 09:32:46 -0800865
Andreas Huberc23dabf2010-11-16 13:05:53 -0800866 int32_t format;
867 const char *component;
868 int32_t decodedWidth, decodedHeight;
869 CHECK(meta->findInt32(kKeyColorFormat, &format));
870 CHECK(meta->findCString(kKeyDecoderComponent, &component));
871 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
872 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
Andreas Hubera67d5382009-12-10 15:32:12 -0800873
Andreas Huber940c8662010-11-16 15:26:30 -0800874 int32_t rotationDegrees;
875 if (!mVideoTrack->getFormat()->findInt32(
876 kKeyRotation, &rotationDegrees)) {
877 rotationDegrees = 0;
878 }
879
Andreas Huberc23dabf2010-11-16 13:05:53 -0800880 mVideoRenderer.clear();
Andreas Hubera67d5382009-12-10 15:32:12 -0800881
Andreas Huberc23dabf2010-11-16 13:05:53 -0800882 // Must ensure that mVideoRenderer's destructor is actually executed
883 // before creating a new one.
884 IPCThreadState::self()->flushCommands();
885
886 if (USE_SURFACE_ALLOC && strncmp(component, "OMX.", 4) == 0) {
887 // Hardware decoders avoid the CPU color conversion by decoding
888 // directly to ANativeBuffers, so we must use a renderer that
889 // just pushes those buffers to the ANativeWindow.
Andreas Huber940c8662010-11-16 15:26:30 -0800890 mVideoRenderer =
891 new AwesomeNativeWindowRenderer(mSurface, rotationDegrees);
Andreas Huberc23dabf2010-11-16 13:05:53 -0800892 } else {
893 // Other decoders are instantiated locally and as a consequence
894 // allocate their buffers in local address space. This renderer
895 // then performs a color conversion and copy to get the data
896 // into the ANativeBuffer.
Andreas Huber1bb0ffd2010-11-22 13:06:35 -0800897 mVideoRenderer = new AwesomeLocalRenderer(mSurface, meta);
Andreas Huber27366fc2009-11-20 09:32:46 -0800898 }
899}
900
901status_t AwesomePlayer::pause() {
902 Mutex::Autolock autoLock(mLock);
Andreas Huber4d61f602010-06-10 11:17:50 -0700903
904 mFlags &= ~CACHE_UNDERRUN;
905
Andreas Huber27366fc2009-11-20 09:32:46 -0800906 return pause_l();
907}
908
Andreas Huberc743f452010-10-05 10:25:34 -0700909status_t AwesomePlayer::pause_l(bool at_eos) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800910 if (!(mFlags & PLAYING)) {
911 return OK;
912 }
913
Andreas Huberb9e63832010-01-26 16:20:10 -0800914 cancelPlayerEvents(true /* keepBufferingGoing */);
Andreas Huber27366fc2009-11-20 09:32:46 -0800915
Andreas Huberce8a1012011-02-11 13:09:36 -0800916 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Andreas Huberc743f452010-10-05 10:25:34 -0700917 if (at_eos) {
918 // If we played the audio stream to completion we
919 // want to make sure that all samples remaining in the audio
920 // track's queue are played out.
921 mAudioPlayer->pause(true /* playPendingSamples */);
922 } else {
923 mAudioPlayer->pause();
924 }
Andreas Huberce8a1012011-02-11 13:09:36 -0800925
926 mFlags &= ~AUDIO_RUNNING;
Andreas Huber27366fc2009-11-20 09:32:46 -0800927 }
928
929 mFlags &= ~PLAYING;
930
Gloria Wangd5770912010-06-22 13:55:38 -0700931 if (mDecryptHandle != NULL) {
932 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
933 Playback::PAUSE, 0);
934 }
935
Andreas Huber27366fc2009-11-20 09:32:46 -0800936 return OK;
937}
938
939bool AwesomePlayer::isPlaying() const {
Andreas Huber4d61f602010-06-10 11:17:50 -0700940 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
Andreas Huber27366fc2009-11-20 09:32:46 -0800941}
942
Andreas Hubere3c01832010-08-16 08:49:37 -0700943void AwesomePlayer::setSurface(const sp<Surface> &surface) {
944 Mutex::Autolock autoLock(mLock);
945
946 mSurface = surface;
947}
948
Andreas Huber27366fc2009-11-20 09:32:46 -0800949void AwesomePlayer::setAudioSink(
950 const sp<MediaPlayerBase::AudioSink> &audioSink) {
951 Mutex::Autolock autoLock(mLock);
952
953 mAudioSink = audioSink;
954}
955
956status_t AwesomePlayer::setLooping(bool shouldLoop) {
957 Mutex::Autolock autoLock(mLock);
958
959 mFlags = mFlags & ~LOOPING;
960
961 if (shouldLoop) {
962 mFlags |= LOOPING;
963 }
964
965 return OK;
966}
967
968status_t AwesomePlayer::getDuration(int64_t *durationUs) {
Andreas Huber252573c2010-03-26 10:17:17 -0700969 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800970
971 if (mDurationUs < 0) {
972 return UNKNOWN_ERROR;
973 }
974
975 *durationUs = mDurationUs;
976
977 return OK;
978}
979
980status_t AwesomePlayer::getPosition(int64_t *positionUs) {
Andreas Hubereeb97d92010-08-27 13:29:08 -0700981 if (mRTSPController != NULL) {
982 *positionUs = mRTSPController->getNormalPlayTimeUs();
983 }
984 else if (mSeeking) {
Andreas Huberddb709c2010-04-07 10:24:35 -0700985 *positionUs = mSeekTimeUs;
986 } else if (mVideoSource != NULL) {
Andreas Huber252573c2010-03-26 10:17:17 -0700987 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800988 *positionUs = mVideoTimeUs;
989 } else if (mAudioPlayer != NULL) {
990 *positionUs = mAudioPlayer->getMediaTimeUs();
991 } else {
992 *positionUs = 0;
993 }
994
995 return OK;
996}
997
998status_t AwesomePlayer::seekTo(int64_t timeUs) {
Andreas Huber10b9b3f2010-10-08 10:16:24 -0700999 if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
Andreas Huber62f7ffe2010-05-06 10:18:05 -07001000 Mutex::Autolock autoLock(mLock);
1001 return seekTo_l(timeUs);
1002 }
1003
1004 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -08001005}
1006
Andreas Huber0c46b692010-10-08 15:21:08 -07001007// static
1008void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) {
1009 static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone();
1010}
1011
1012void AwesomePlayer::onRTSPSeekDone() {
1013 notifyListener_l(MEDIA_SEEK_COMPLETE);
1014 mSeekNotificationSent = true;
1015}
1016
Andreas Huber27366fc2009-11-20 09:32:46 -08001017status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
Andreas Hubere0dd7d32010-08-24 14:33:58 -07001018 if (mRTSPController != NULL) {
Andreas Huber0c46b692010-10-08 15:21:08 -07001019 mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this);
Andreas Hubere0dd7d32010-08-24 14:33:58 -07001020 return OK;
1021 }
1022
Andreas Huber4d61f602010-06-10 11:17:50 -07001023 if (mFlags & CACHE_UNDERRUN) {
1024 mFlags &= ~CACHE_UNDERRUN;
1025 play_l();
1026 }
1027
Andreas Huber27366fc2009-11-20 09:32:46 -08001028 mSeeking = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001029 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -08001030 mSeekTimeUs = timeUs;
Andreas Huber971305d2010-07-07 13:35:27 -07001031 mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
Andreas Huber27366fc2009-11-20 09:32:46 -08001032
1033 seekAudioIfNecessary_l();
1034
Andreas Huber8e2b9412010-03-31 09:40:15 -07001035 if (!(mFlags & PLAYING)) {
1036 LOGV("seeking while paused, sending SEEK_COMPLETE notification"
1037 " immediately.");
1038
1039 notifyListener_l(MEDIA_SEEK_COMPLETE);
1040 mSeekNotificationSent = true;
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001041
1042 if ((mFlags & PREPARED) && mVideoSource != NULL) {
1043 mFlags |= SEEK_PREVIEW;
1044 postVideoEvent_l();
1045 }
Andreas Huber8e2b9412010-03-31 09:40:15 -07001046 }
1047
Andreas Huber27366fc2009-11-20 09:32:46 -08001048 return OK;
1049}
1050
1051void AwesomePlayer::seekAudioIfNecessary_l() {
Andreas Huber7085b6842010-02-03 16:02:02 -08001052 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001053 mAudioPlayer->seekTo(mSeekTimeUs);
1054
Andreas Huber70d10c02010-02-03 11:37:29 -08001055 mWatchForAudioSeekComplete = true;
1056 mWatchForAudioEOS = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001057 mSeekNotificationSent = false;
Gloria Wangd5770912010-06-22 13:55:38 -07001058
1059 if (mDecryptHandle != NULL) {
1060 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1061 Playback::PAUSE, 0);
1062 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1063 Playback::START, mSeekTimeUs / 1000);
1064 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001065 }
1066}
1067
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001068void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
1069 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001070
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001071 mAudioTrack = source;
1072}
1073
1074status_t AwesomePlayer::initAudioDecoder() {
1075 sp<MetaData> meta = mAudioTrack->getFormat();
Andreas Huberc79827a2010-01-05 10:54:55 -08001076
1077 const char *mime;
1078 CHECK(meta->findCString(kKeyMIMEType, &mime));
1079
1080 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001081 mAudioSource = mAudioTrack;
Andreas Huberc79827a2010-01-05 10:54:55 -08001082 } else {
1083 mAudioSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001084 mClient.interface(), mAudioTrack->getFormat(),
Andreas Huberc79827a2010-01-05 10:54:55 -08001085 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001086 mAudioTrack);
Andreas Huberc79827a2010-01-05 10:54:55 -08001087 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001088
1089 if (mAudioSource != NULL) {
1090 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001091 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -07001092 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001093 if (mDurationUs < 0 || durationUs > mDurationUs) {
1094 mDurationUs = durationUs;
1095 }
1096 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001097
Andreas Huber3c78a1b2010-05-13 09:15:21 -07001098 status_t err = mAudioSource->start();
1099
1100 if (err != OK) {
1101 mAudioSource.clear();
1102 return err;
1103 }
Andreas Huberd0332ad2010-04-12 16:05:57 -07001104 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
1105 // For legacy reasons we're simply going to ignore the absence
1106 // of an audio decoder for QCELP instead of aborting playback
1107 // altogether.
1108 return OK;
1109 }
Andreas Huberdc9927d2010-03-08 15:46:13 -08001110
Andreas Huber27366fc2009-11-20 09:32:46 -08001111 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
1112}
1113
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001114void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
1115 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001116
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001117 mVideoTrack = source;
1118}
1119
Andreas Huber4c19bf92010-09-08 14:32:20 -07001120status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001121 mVideoSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001122 mClient.interface(), mVideoTrack->getFormat(),
Andreas Huber27366fc2009-11-20 09:32:46 -08001123 false, // createEncoder
Andreas Huber57648e42010-08-04 10:14:30 -07001124 mVideoTrack,
Andreas Huber6a1f5f92010-11-15 09:03:03 -08001125 NULL, flags, USE_SURFACE_ALLOC ? mSurface : NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001126
1127 if (mVideoSource != NULL) {
1128 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001129 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -07001130 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001131 if (mDurationUs < 0 || durationUs > mDurationUs) {
1132 mDurationUs = durationUs;
1133 }
1134 }
1135
Andreas Huber1919e5a2010-05-20 10:37:06 -07001136 status_t err = mVideoSource->start();
1137
1138 if (err != OK) {
1139 mVideoSource.clear();
1140 return err;
1141 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001142 }
1143
1144 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
1145}
1146
Andreas Huber4d450a82010-10-19 09:34:44 -07001147void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001148 if (!mSeeking || (mFlags & SEEK_PREVIEW)) {
Andreas Huber4d450a82010-10-19 09:34:44 -07001149 return;
1150 }
1151
1152 if (mAudioPlayer != NULL) {
Jamie Gennis6913c612010-10-20 15:55:43 -07001153 LOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
Andreas Huber4d450a82010-10-19 09:34:44 -07001154
1155 // If we don't have a video time, seek audio to the originally
1156 // requested seek time instead.
1157
1158 mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
Andreas Huber4d450a82010-10-19 09:34:44 -07001159 mWatchForAudioSeekComplete = true;
Andreas Huber4d450a82010-10-19 09:34:44 -07001160 } else if (!mSeekNotificationSent) {
1161 // If we're playing video only, report seek complete now,
1162 // otherwise audio player will notify us later.
1163 notifyListener_l(MEDIA_SEEK_COMPLETE);
1164 }
1165
1166 mFlags |= FIRST_FRAME;
1167 mSeeking = false;
1168 mSeekNotificationSent = false;
Gloria Wang3f9a8192010-10-29 14:50:17 -07001169
1170 if (mDecryptHandle != NULL) {
1171 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1172 Playback::PAUSE, 0);
1173 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1174 Playback::START, videoTimeUs / 1000);
1175 }
Andreas Huber4d450a82010-10-19 09:34:44 -07001176}
1177
Andreas Huber6be780e2010-02-08 14:40:30 -08001178void AwesomePlayer::onVideoEvent() {
Andreas Huber27366fc2009-11-20 09:32:46 -08001179 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -08001180 if (!mVideoEventPending) {
1181 // The event has been cancelled in reset_l() but had already
1182 // been scheduled for execution at that time.
1183 return;
1184 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001185 mVideoEventPending = false;
1186
1187 if (mSeeking) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001188 if (mVideoBuffer) {
1189 mVideoBuffer->release();
1190 mVideoBuffer = NULL;
1191 }
Andreas Huber4d61f602010-06-10 11:17:50 -07001192
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001193 if (mCachedSource != NULL && mAudioSource != NULL
1194 && !(mFlags & SEEK_PREVIEW)) {
Andreas Huber4d61f602010-06-10 11:17:50 -07001195 // We're going to seek the video source first, followed by
1196 // the audio source.
1197 // In order to avoid jumps in the DataSource offset caused by
1198 // the audio codec prefetching data from the old locations
1199 // while the video codec is already reading data from the new
1200 // locations, we'll "pause" the audio source, causing it to
1201 // stop reading input data until a subsequent seek.
1202
Andreas Huberce8a1012011-02-11 13:09:36 -08001203 if (mAudioPlayer != NULL && (mFlags & AUDIO_RUNNING)) {
Andreas Huber4d61f602010-06-10 11:17:50 -07001204 mAudioPlayer->pause();
Andreas Huberce8a1012011-02-11 13:09:36 -08001205
1206 mFlags &= ~AUDIO_RUNNING;
Andreas Huber4d61f602010-06-10 11:17:50 -07001207 }
1208 mAudioSource->pause();
1209 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001210 }
1211
1212 if (!mVideoBuffer) {
1213 MediaSource::ReadOptions options;
1214 if (mSeeking) {
1215 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
1216
Andreas Huber6624c9f2010-07-20 15:04:28 -07001217 options.setSeekTo(
1218 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
Andreas Huber27366fc2009-11-20 09:32:46 -08001219 }
1220 for (;;) {
1221 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberb1f5ee42009-12-14 15:34:11 -08001222 options.clearSeekTo();
Andreas Huber27366fc2009-11-20 09:32:46 -08001223
1224 if (err != OK) {
Andreas Huber52b52cd2010-11-23 11:41:34 -08001225 CHECK(mVideoBuffer == NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001226
1227 if (err == INFO_FORMAT_CHANGED) {
1228 LOGV("VideoSource signalled format change.");
1229
Andreas Hubere3c01832010-08-16 08:49:37 -07001230 notifyVideoSize_l();
1231
Andreas Huber7085b6842010-02-03 16:02:02 -08001232 if (mVideoRenderer != NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001233 mVideoRendererIsPreview = false;
Andreas Huber7085b6842010-02-03 16:02:02 -08001234 initRenderer_l();
1235 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001236 continue;
1237 }
1238
Andreas Huber4d450a82010-10-19 09:34:44 -07001239 // So video playback is complete, but we may still have
1240 // a seek request pending that needs to be applied
1241 // to the audio track.
1242 if (mSeeking) {
1243 LOGV("video stream ended while seeking!");
1244 }
1245 finishSeekIfNecessary(-1);
1246
Andreas Huber971305d2010-07-07 13:35:27 -07001247 mFlags |= VIDEO_AT_EOS;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001248 postStreamDoneEvent_l(err);
Andreas Huber27366fc2009-11-20 09:32:46 -08001249 return;
1250 }
1251
Andreas Hubera67d5382009-12-10 15:32:12 -08001252 if (mVideoBuffer->range_length() == 0) {
Andreas Huber6ddcf012009-12-10 15:32:12 -08001253 // Some decoders, notably the PV AVC software decoder
1254 // return spurious empty buffers that we just want to ignore.
1255
Andreas Hubera67d5382009-12-10 15:32:12 -08001256 mVideoBuffer->release();
1257 mVideoBuffer = NULL;
1258 continue;
1259 }
1260
Andreas Huber27366fc2009-11-20 09:32:46 -08001261 break;
1262 }
1263 }
1264
1265 int64_t timeUs;
1266 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1267
Andreas Huber252573c2010-03-26 10:17:17 -07001268 {
1269 Mutex::Autolock autoLock(mMiscStateLock);
1270 mVideoTimeUs = timeUs;
1271 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001272
Andreas Huber614d22c2010-10-29 15:47:52 -07001273 bool wasSeeking = mSeeking;
Andreas Huber4d450a82010-10-19 09:34:44 -07001274 finishSeekIfNecessary(timeUs);
Andreas Huber27366fc2009-11-20 09:32:46 -08001275
Andreas Huberce8a1012011-02-11 13:09:36 -08001276 if (mAudioPlayer != NULL && !(mFlags & (AUDIO_RUNNING | SEEK_PREVIEW))) {
1277 status_t err = startAudioPlayer_l();
1278 if (err != OK) {
1279 LOGE("Startung the audio player failed w/ err %d", err);
1280 return;
1281 }
1282 }
1283
Andreas Huber971305d2010-07-07 13:35:27 -07001284 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
1285
Andreas Huber27366fc2009-11-20 09:32:46 -08001286 if (mFlags & FIRST_FRAME) {
1287 mFlags &= ~FIRST_FRAME;
pmehendale28f939d2011-01-06 14:43:49 -08001288 mSinceLastDropped = 0;
Andreas Huber971305d2010-07-07 13:35:27 -07001289 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
Andreas Huber27366fc2009-11-20 09:32:46 -08001290 }
1291
1292 int64_t realTimeUs, mediaTimeUs;
Andreas Huber971305d2010-07-07 13:35:27 -07001293 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
Andreas Huber27366fc2009-11-20 09:32:46 -08001294 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1295 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1296 }
1297
Andreas Huberb2934b12011-02-08 10:18:41 -08001298 if (!wasSeeking) {
Andreas Huber614d22c2010-10-29 15:47:52 -07001299 // Let's display the first frame after seeking right away.
Andreas Huberf88f8442010-08-10 11:18:36 -07001300
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001301 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
Andreas Huber27366fc2009-11-20 09:32:46 -08001302
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001303 int64_t latenessUs = nowUs - timeUs;
1304
1305 if (latenessUs > 40000) {
1306 // We're more than 40ms late.
1307 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
1308 if ( mSinceLastDropped > FRAME_DROP_FREQ)
1309 {
1310 LOGV("we're late by %lld us (%.2f secs) dropping one after %d frames", latenessUs, latenessUs / 1E6, mSinceLastDropped);
1311 mSinceLastDropped = 0;
1312 mVideoBuffer->release();
1313 mVideoBuffer = NULL;
1314
1315 postVideoEvent_l();
1316 return;
1317 }
1318 }
1319
1320 if (latenessUs < -10000) {
1321 // We're more than 10ms early.
1322
1323 postVideoEvent_l(10000);
pmehendale28f939d2011-01-06 14:43:49 -08001324 return;
1325 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001326 }
1327
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001328 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
1329 mVideoRendererIsPreview = false;
1330
Andreas Huber7085b6842010-02-03 16:02:02 -08001331 initRenderer_l();
1332 }
1333
1334 if (mVideoRenderer != NULL) {
pmehendale28f939d2011-01-06 14:43:49 -08001335 mSinceLastDropped++;
Andreas Huber7085b6842010-02-03 16:02:02 -08001336 mVideoRenderer->render(mVideoBuffer);
1337 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001338
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001339 mVideoBuffer->release();
Andreas Huber27366fc2009-11-20 09:32:46 -08001340 mVideoBuffer = NULL;
1341
Andreas Huber0a84f4f2011-02-07 11:43:12 -08001342 if (wasSeeking && (mFlags & SEEK_PREVIEW)) {
1343 mFlags &= ~SEEK_PREVIEW;
1344 return;
1345 }
1346
Andreas Huber27366fc2009-11-20 09:32:46 -08001347 postVideoEvent_l();
1348}
1349
1350void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
1351 if (mVideoEventPending) {
1352 return;
1353 }
1354
1355 mVideoEventPending = true;
1356 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1357}
1358
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001359void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001360 if (mStreamDoneEventPending) {
1361 return;
1362 }
1363 mStreamDoneEventPending = true;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001364
1365 mStreamDoneStatus = status;
Andreas Huber27366fc2009-11-20 09:32:46 -08001366 mQueue.postEvent(mStreamDoneEvent);
1367}
1368
Andreas Huberb9e63832010-01-26 16:20:10 -08001369void AwesomePlayer::postBufferingEvent_l() {
Andreas Huberb9e63832010-01-26 16:20:10 -08001370 if (mBufferingEventPending) {
1371 return;
1372 }
1373 mBufferingEventPending = true;
1374 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1375}
1376
Andreas Huber52c78322011-01-11 15:05:28 -08001377void AwesomePlayer::postVideoLagEvent_l() {
1378 if (mVideoLagEventPending) {
1379 return;
1380 }
1381 mVideoLagEventPending = true;
1382 mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
1383}
1384
Andreas Huber70d10c02010-02-03 11:37:29 -08001385void AwesomePlayer::postCheckAudioStatusEvent_l() {
1386 if (mAudioStatusEventPending) {
1387 return;
1388 }
1389 mAudioStatusEventPending = true;
Andreas Huber2b359ed2010-09-28 11:56:39 -07001390 mQueue.postEvent(mCheckAudioStatusEvent);
Andreas Huber70d10c02010-02-03 11:37:29 -08001391}
1392
1393void AwesomePlayer::onCheckAudioStatus() {
1394 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -08001395 if (!mAudioStatusEventPending) {
1396 // Event was dispatched and while we were blocking on the mutex,
1397 // has already been cancelled.
1398 return;
1399 }
1400
Andreas Huber70d10c02010-02-03 11:37:29 -08001401 mAudioStatusEventPending = false;
1402
1403 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1404 mWatchForAudioSeekComplete = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001405
1406 if (!mSeekNotificationSent) {
1407 notifyListener_l(MEDIA_SEEK_COMPLETE);
1408 mSeekNotificationSent = true;
1409 }
Andreas Huberddb709c2010-04-07 10:24:35 -07001410
1411 mSeeking = false;
Andreas Huber70d10c02010-02-03 11:37:29 -08001412 }
1413
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001414 status_t finalStatus;
1415 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
Andreas Huber70d10c02010-02-03 11:37:29 -08001416 mWatchForAudioEOS = false;
Andreas Huber971305d2010-07-07 13:35:27 -07001417 mFlags |= AUDIO_AT_EOS;
1418 mFlags |= FIRST_FRAME;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001419 postStreamDoneEvent_l(finalStatus);
Andreas Huber70d10c02010-02-03 11:37:29 -08001420 }
Andreas Huber70d10c02010-02-03 11:37:29 -08001421}
1422
Andreas Huber6be780e2010-02-08 14:40:30 -08001423status_t AwesomePlayer::prepare() {
1424 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001425 return prepare_l();
1426}
Andreas Huber6be780e2010-02-08 14:40:30 -08001427
Andreas Huberffdf4782010-02-09 14:05:43 -08001428status_t AwesomePlayer::prepare_l() {
1429 if (mFlags & PREPARED) {
1430 return OK;
1431 }
1432
1433 if (mFlags & PREPARING) {
1434 return UNKNOWN_ERROR;
1435 }
1436
1437 mIsAsyncPrepare = false;
Andreas Huber6be780e2010-02-08 14:40:30 -08001438 status_t err = prepareAsync_l();
1439
1440 if (err != OK) {
1441 return err;
1442 }
1443
Andreas Huberffdf4782010-02-09 14:05:43 -08001444 while (mFlags & PREPARING) {
Andreas Huber6be780e2010-02-08 14:40:30 -08001445 mPreparedCondition.wait(mLock);
1446 }
1447
Andreas Huberffdf4782010-02-09 14:05:43 -08001448 return mPrepareResult;
Andreas Huber6be780e2010-02-08 14:40:30 -08001449}
1450
1451status_t AwesomePlayer::prepareAsync() {
1452 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001453
1454 if (mFlags & PREPARING) {
1455 return UNKNOWN_ERROR; // async prepare already pending
1456 }
1457
1458 mIsAsyncPrepare = true;
Andreas Huber6be780e2010-02-08 14:40:30 -08001459 return prepareAsync_l();
1460}
1461
1462status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001463 if (mFlags & PREPARING) {
1464 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huber6be780e2010-02-08 14:40:30 -08001465 }
1466
Andreas Huber406a18b2010-02-18 16:45:13 -08001467 if (!mQueueStarted) {
1468 mQueue.start();
1469 mQueueStarted = true;
1470 }
1471
Andreas Huberffdf4782010-02-09 14:05:43 -08001472 mFlags |= PREPARING;
Andreas Huber6be780e2010-02-08 14:40:30 -08001473 mAsyncPrepareEvent = new AwesomeEvent(
1474 this, &AwesomePlayer::onPrepareAsyncEvent);
1475
1476 mQueue.postEvent(mAsyncPrepareEvent);
1477
1478 return OK;
1479}
1480
Andreas Huberffdf4782010-02-09 14:05:43 -08001481status_t AwesomePlayer::finishSetDataSource_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001482 sp<DataSource> dataSource;
1483
1484 if (!strncasecmp("http://", mUri.string(), 7)) {
Andreas Huber4d61f602010-06-10 11:17:50 -07001485 mConnectingDataSource = new NuHTTPDataSource;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001486
1487 mLock.unlock();
Andreas Huber3a53dc52010-06-11 09:57:46 -07001488 status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001489 mLock.lock();
1490
1491 if (err != OK) {
1492 mConnectingDataSource.clear();
1493
1494 LOGI("mConnectingDataSource->connect() returned %d", err);
1495 return err;
1496 }
1497
Andreas Huber4d61f602010-06-10 11:17:50 -07001498#if 0
1499 mCachedSource = new NuCachedSource2(
1500 new ThrottledSource(
1501 mConnectingDataSource, 50 * 1024 /* bytes/sec */));
1502#else
1503 mCachedSource = new NuCachedSource2(mConnectingDataSource);
1504#endif
Andreas Huberedbb4d82010-03-12 08:59:22 -08001505 mConnectingDataSource.clear();
Andreas Huber4d61f602010-06-10 11:17:50 -07001506
1507 dataSource = mCachedSource;
Andreas Huber96346652011-01-19 15:07:19 -08001508
1509 // We're going to prefill the cache before trying to instantiate
1510 // the extractor below, as the latter is an operation that otherwise
1511 // could block on the datasource for a significant amount of time.
1512 // During that time we'd be unable to abort the preparation phase
1513 // without this prefill.
1514
1515 mLock.unlock();
1516
1517 for (;;) {
1518 status_t finalStatus;
1519 size_t cachedDataRemaining =
1520 mCachedSource->approxDataRemaining(&finalStatus);
1521
1522 if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
1523 || (mFlags & PREPARE_CANCELLED)) {
1524 break;
1525 }
1526
1527 usleep(200000);
1528 }
1529
1530 mLock.lock();
1531
1532 if (mFlags & PREPARE_CANCELLED) {
1533 LOGI("Prepare cancelled while waiting for initial cache fill.");
1534 return UNKNOWN_ERROR;
1535 }
Andreas Huber7a747b82010-06-07 15:19:40 -07001536 } else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
1537 if (mLooper == NULL) {
1538 mLooper = new ALooper;
Andreas Huberc4e0b702010-08-27 15:21:07 -07001539 mLooper->setName("rtsp");
Andreas Huber7a747b82010-06-07 15:19:40 -07001540 mLooper->start();
1541 }
1542 mRTSPController = new ARTSPController(mLooper);
Andreas Hubercb218792011-02-14 14:14:23 -08001543 mConnectingRTSPController = mRTSPController;
1544
1545 mLock.unlock();
Andreas Huber7a747b82010-06-07 15:19:40 -07001546 status_t err = mRTSPController->connect(mUri.string());
Andreas Hubercb218792011-02-14 14:14:23 -08001547 mLock.lock();
1548
1549 mConnectingRTSPController.clear();
Andreas Huber202348e2010-06-07 14:35:29 -07001550
Andreas Huber7a747b82010-06-07 15:19:40 -07001551 LOGI("ARTSPController::connect returned %d", err);
1552
1553 if (err != OK) {
1554 mRTSPController.clear();
1555 return err;
1556 }
1557
1558 sp<MediaExtractor> extractor = mRTSPController.get();
Andreas Huber202348e2010-06-07 14:35:29 -07001559 return setDataSource_l(extractor);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001560 } else {
1561 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1562 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001563
1564 if (dataSource == NULL) {
1565 return UNKNOWN_ERROR;
1566 }
1567
1568 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1569
1570 if (extractor == NULL) {
1571 return UNKNOWN_ERROR;
1572 }
1573
Gloria Wangd5770912010-06-22 13:55:38 -07001574 dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
Gloria Wangc2c22e72010-11-01 15:53:16 -07001575 if (mDecryptHandle != NULL) {
Gloria Wangadc4d9c2011-02-08 13:24:08 -08001576 CHECK(mDrmManagerClient);
Gloria Wangc2c22e72010-11-01 15:53:16 -07001577 if (RightsStatus::RIGHTS_VALID == mDecryptHandle->status) {
1578 if (DecryptApiType::WV_BASED == mDecryptHandle->decryptApiType) {
1579 LOGD("Setting mCachedSource to NULL for WVM\n");
1580 mCachedSource.clear();
1581 }
1582 } else {
1583 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
1584 }
Gloria Wangd5770912010-06-22 13:55:38 -07001585 }
1586
Andreas Huberffdf4782010-02-09 14:05:43 -08001587 return setDataSource_l(extractor);
1588}
1589
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001590void AwesomePlayer::abortPrepare(status_t err) {
1591 CHECK(err != OK);
1592
1593 if (mIsAsyncPrepare) {
1594 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1595 }
1596
1597 mPrepareResult = err;
Andreas Hubereaf2c5a2010-10-19 12:18:51 -07001598 mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001599 mAsyncPrepareEvent = NULL;
1600 mPreparedCondition.broadcast();
1601}
1602
Andreas Huberf71daba2010-03-24 09:24:40 -07001603// static
1604bool AwesomePlayer::ContinuePreparation(void *cookie) {
1605 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
1606
1607 return (me->mFlags & PREPARE_CANCELLED) == 0;
1608}
1609
Andreas Huber6be780e2010-02-08 14:40:30 -08001610void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001611 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001612
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001613 if (mFlags & PREPARE_CANCELLED) {
1614 LOGI("prepare was cancelled before doing anything");
1615 abortPrepare(UNKNOWN_ERROR);
1616 return;
1617 }
1618
1619 if (mUri.size() > 0) {
1620 status_t err = finishSetDataSource_l();
1621
1622 if (err != OK) {
1623 abortPrepare(err);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001624 return;
1625 }
Andreas Huber6be780e2010-02-08 14:40:30 -08001626 }
1627
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001628 if (mVideoTrack != NULL && mVideoSource == NULL) {
1629 status_t err = initVideoDecoder();
Andreas Huber6be780e2010-02-08 14:40:30 -08001630
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001631 if (err != OK) {
1632 abortPrepare(err);
1633 return;
1634 }
1635 }
1636
1637 if (mAudioTrack != NULL && mAudioSource == NULL) {
1638 status_t err = initAudioDecoder();
1639
1640 if (err != OK) {
1641 abortPrepare(err);
1642 return;
1643 }
1644 }
1645
Andreas Hubereaf2c5a2010-10-19 12:18:51 -07001646 mFlags |= PREPARING_CONNECTED;
1647
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001648 if (mCachedSource != NULL || mRTSPController != NULL) {
1649 postBufferingEvent_l();
1650 } else {
1651 finishAsyncPrepare_l();
1652 }
1653}
1654
1655void AwesomePlayer::finishAsyncPrepare_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001656 if (mIsAsyncPrepare) {
Andreas Hubere3c01832010-08-16 08:49:37 -07001657 if (mVideoSource == NULL) {
Andreas Huberffdf4782010-02-09 14:05:43 -08001658 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1659 } else {
Andreas Hubere3c01832010-08-16 08:49:37 -07001660 notifyVideoSize_l();
Andreas Huberffdf4782010-02-09 14:05:43 -08001661 }
1662
1663 notifyListener_l(MEDIA_PREPARED);
Andreas Huber6be780e2010-02-08 14:40:30 -08001664 }
1665
Andreas Huberffdf4782010-02-09 14:05:43 -08001666 mPrepareResult = OK;
Andreas Hubereaf2c5a2010-10-19 12:18:51 -07001667 mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
Andreas Huberffdf4782010-02-09 14:05:43 -08001668 mFlags |= PREPARED;
Andreas Huber6be780e2010-02-08 14:40:30 -08001669 mAsyncPrepareEvent = NULL;
Andreas Huberffdf4782010-02-09 14:05:43 -08001670 mPreparedCondition.broadcast();
Andreas Huber6be780e2010-02-08 14:40:30 -08001671}
1672
Andreas Huber62f7ffe2010-05-06 10:18:05 -07001673uint32_t AwesomePlayer::flags() const {
1674 return mExtractorFlags;
1675}
1676
Andreas Huber2b359ed2010-09-28 11:56:39 -07001677void AwesomePlayer::postAudioEOS() {
1678 postCheckAudioStatusEvent_l();
1679}
1680
1681void AwesomePlayer::postAudioSeekComplete() {
1682 postCheckAudioStatusEvent_l();
1683}
1684
Andreas Huber27366fc2009-11-20 09:32:46 -08001685} // namespace android