blob: 7613d040f022350a3b13cc63bbbab17a98695367 [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 Huber57648e42010-08-04 10:14:30 -070030#include "ARTPSession.h"
31#include "APacketSource.h"
32#include "ASessionDescription.h"
33#include "UDPPusher.h"
34
Andreas Hubera67d5382009-12-10 15:32:12 -080035#include <binder/IPCThreadState.h>
Andreas Huber52b52cd2010-11-23 11:41:34 -080036#include <binder/MemoryDealer.h>
37#include <media/IStreamSource.h>
38#include <media/stagefright/foundation/hexdump.h>
39#include <media/stagefright/foundation/ADebug.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080040#include <media/stagefright/AudioPlayer.h>
41#include <media/stagefright/DataSource.h>
42#include <media/stagefright/FileSource.h>
43#include <media/stagefright/MediaBuffer.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080044#include <media/stagefright/MediaDefs.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080045#include <media/stagefright/MediaExtractor.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080046#include <media/stagefright/MediaSource.h>
47#include <media/stagefright/MetaData.h>
48#include <media/stagefright/OMXCodec.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080049
Andreas Hubere3c01832010-08-16 08:49:37 -070050#include <surfaceflinger/Surface.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 Huberb5590842010-12-03 16:12:25 -080054#include "include/LiveSession.h"
Andreas Huber202348e2010-06-07 14:35:29 -070055
Andreas Huber6a1f5f92010-11-15 09:03:03 -080056#define USE_SURFACE_ALLOC 1
57
Andreas Huber27366fc2009-11-20 09:32:46 -080058namespace android {
59
Andreas Huber87ab9cd2010-09-03 13:20:33 -070060static int64_t kLowWaterMarkUs = 2000000ll; // 2secs
61static int64_t kHighWaterMarkUs = 10000000ll; // 10secs
62
Andreas Huber27366fc2009-11-20 09:32:46 -080063struct AwesomeEvent : public TimedEventQueue::Event {
Andreas Huber6be780e2010-02-08 14:40:30 -080064 AwesomeEvent(
65 AwesomePlayer *player,
66 void (AwesomePlayer::*method)())
Andreas Huber27366fc2009-11-20 09:32:46 -080067 : mPlayer(player),
Andreas Huber6be780e2010-02-08 14:40:30 -080068 mMethod(method) {
Andreas Huber27366fc2009-11-20 09:32:46 -080069 }
70
71protected:
72 virtual ~AwesomeEvent() {}
73
74 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
Andreas Huber6be780e2010-02-08 14:40:30 -080075 (mPlayer->*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080076 }
77
78private:
79 AwesomePlayer *mPlayer;
Andreas Huber6be780e2010-02-08 14:40:30 -080080 void (AwesomePlayer::*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080081
82 AwesomeEvent(const AwesomeEvent &);
83 AwesomeEvent &operator=(const AwesomeEvent &);
84};
85
Andreas Huber1314e732009-12-14 14:18:22 -080086struct AwesomeLocalRenderer : public AwesomeRenderer {
87 AwesomeLocalRenderer(
Andreas Huber1bb0ffd2010-11-22 13:06:35 -080088 const sp<Surface> &surface, const sp<MetaData> &meta)
89 : mTarget(new SoftwareRenderer(surface, meta)) {
Andreas Huber1314e732009-12-14 14:18:22 -080090 }
91
92 virtual void render(MediaBuffer *buffer) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -080093 render((const uint8_t *)buffer->data() + buffer->range_offset(),
94 buffer->range_length());
95 }
96
97 void render(const void *data, size_t size) {
98 mTarget->render(data, size, NULL);
Andreas Huber1314e732009-12-14 14:18:22 -080099 }
100
101protected:
102 virtual ~AwesomeLocalRenderer() {
103 delete mTarget;
104 mTarget = NULL;
105 }
106
107private:
Andreas Huberc23dabf2010-11-16 13:05:53 -0800108 SoftwareRenderer *mTarget;
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800109
Andreas Huber1314e732009-12-14 14:18:22 -0800110 AwesomeLocalRenderer(const AwesomeLocalRenderer &);
111 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
112};
113
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700114struct AwesomeNativeWindowRenderer : public AwesomeRenderer {
Andreas Huber940c8662010-11-16 15:26:30 -0800115 AwesomeNativeWindowRenderer(
116 const sp<ANativeWindow> &nativeWindow,
117 int32_t rotationDegrees)
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700118 : mNativeWindow(nativeWindow) {
Andreas Huber940c8662010-11-16 15:26:30 -0800119 applyRotation(rotationDegrees);
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700120 }
121
122 virtual void render(MediaBuffer *buffer) {
123 status_t err = mNativeWindow->queueBuffer(
124 mNativeWindow.get(), buffer->graphicBuffer().get());
125 if (err != 0) {
126 LOGE("queueBuffer failed with error %s (%d)", strerror(-err),
127 -err);
128 return;
129 }
130
131 sp<MetaData> metaData = buffer->meta_data();
132 metaData->setInt32(kKeyRendered, 1);
133 }
134
135protected:
136 virtual ~AwesomeNativeWindowRenderer() {}
137
138private:
139 sp<ANativeWindow> mNativeWindow;
140
Andreas Huber940c8662010-11-16 15:26:30 -0800141 void applyRotation(int32_t rotationDegrees) {
142 uint32_t transform;
143 switch (rotationDegrees) {
144 case 0: transform = 0; break;
145 case 90: transform = HAL_TRANSFORM_ROT_90; break;
146 case 180: transform = HAL_TRANSFORM_ROT_180; break;
147 case 270: transform = HAL_TRANSFORM_ROT_270; break;
148 default: transform = 0; break;
149 }
150
151 if (transform) {
152 CHECK_EQ(0, native_window_set_buffers_transform(
153 mNativeWindow.get(), transform));
154 }
155 }
156
Jamie Gennis58a36ad2010-10-07 14:08:38 -0700157 AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &);
158 AwesomeNativeWindowRenderer &operator=(
159 const AwesomeNativeWindowRenderer &);
160};
161
Andreas Huber52b52cd2010-11-23 11:41:34 -0800162////////////////////////////////////////////////////////////////////////////////
163
164struct QueueDataSource;
165
166struct QueueListener : public BnStreamListener {
167 QueueListener(QueueDataSource *owner)
168 : mOwner(owner) {
169 }
170
171 void clearOwner();
172
173 virtual void queueBuffer(size_t index, size_t size);
Andreas Huberae9d5072010-12-06 10:36:06 -0800174
175 virtual void issueCommand(
176 Command cmd, bool synchronous, const sp<AMessage> &msg);
Andreas Huber52b52cd2010-11-23 11:41:34 -0800177
178private:
179 Mutex mLock;
180
181 QueueDataSource *mOwner;
182
183 DISALLOW_EVIL_CONSTRUCTORS(QueueListener);
184};
185
186struct QueueDataSource : public DataSource {
187 QueueDataSource(const sp<IStreamSource> &source);
188
189 virtual status_t initCheck() const;
190
191 virtual ssize_t readAt(off64_t offset, void *data, size_t size);
192
193 virtual void queueBuffer(size_t index, size_t size);
Andreas Huberae9d5072010-12-06 10:36:06 -0800194
195 virtual void issueCommand(
196 IStreamListener::Command cmd,
197 bool synchronous,
198 const sp<AMessage> &msg);
Andreas Huber52b52cd2010-11-23 11:41:34 -0800199
200protected:
201 virtual ~QueueDataSource();
202
203private:
204 enum {
205 kNumBuffers = 16
206 };
207
Andreas Huberae9d5072010-12-06 10:36:06 -0800208 struct QueueEntry {
209 bool mIsCommand;
210
211 IStreamListener::Command mCommand;
212 sp<AMessage> mCommandMessage;
213
Andreas Huber52b52cd2010-11-23 11:41:34 -0800214 size_t mIndex;
215 size_t mOffset;
216 size_t mSize;
217 };
218
219 Mutex mLock;
220 Condition mCondition;
221
222 sp<IStreamSource> mSource;
223 sp<QueueListener> mListener;
224 sp<MemoryDealer> mDealer;
225 Vector<sp<IMemory> > mBuffers;
226
Andreas Huberae9d5072010-12-06 10:36:06 -0800227 List<QueueEntry> mQueue;
Andreas Huber52b52cd2010-11-23 11:41:34 -0800228
229 off64_t mPosition;
230 bool mEOS;
231
232 DISALLOW_EVIL_CONSTRUCTORS(QueueDataSource);
233};
234
235QueueDataSource::QueueDataSource(const sp<IStreamSource> &source)
236 : mSource(source),
237 mPosition(0),
238 mEOS(false) {
239 mListener = new QueueListener(this);
240 mSource->setListener(mListener);
241
Andreas Huberae9d5072010-12-06 10:36:06 -0800242 static const size_t kBufferSize = (8192 / 188) * 188;
Andreas Huber52b52cd2010-11-23 11:41:34 -0800243
244 mDealer = new MemoryDealer(kNumBuffers * kBufferSize);
245 for (size_t i = 0; i < kNumBuffers; ++i) {
246 sp<IMemory> mem = mDealer->allocate(kBufferSize);
247 CHECK(mem != NULL);
248
249 mBuffers.push(mem);
250 }
251 mSource->setBuffers(mBuffers);
252
253 for (size_t i = 0; i < kNumBuffers; ++i) {
254 mSource->onBufferAvailable(i);
255 }
256}
257
258QueueDataSource::~QueueDataSource() {
259 Mutex::Autolock autoLock(mLock);
260
Andreas Huber52b52cd2010-11-23 11:41:34 -0800261 mListener->clearOwner();
262}
263
264status_t QueueDataSource::initCheck() const {
265 return OK;
266}
267
268ssize_t QueueDataSource::readAt(off64_t offset, void *data, size_t size) {
269 if (offset != mPosition) {
270 return -EPIPE;
271 }
272
273 Mutex::Autolock autoLock(mLock);
274
Andreas Huberae9d5072010-12-06 10:36:06 -0800275 if (mEOS) {
276 return ERROR_END_OF_STREAM;
277 }
278
Andreas Huber52b52cd2010-11-23 11:41:34 -0800279 size_t sizeDone = 0;
280
281 while (sizeDone < size) {
Andreas Huberae9d5072010-12-06 10:36:06 -0800282 while (mQueue.empty()) {
Andreas Huber52b52cd2010-11-23 11:41:34 -0800283 mCondition.wait(mLock);
284 }
285
Andreas Huberae9d5072010-12-06 10:36:06 -0800286 QueueEntry &entry = *mQueue.begin();
287
288 if (entry.mIsCommand) {
289 switch (entry.mCommand) {
290 case IStreamListener::EOS:
291 {
292 mEOS = true;
293
294 if (sizeDone > 0) {
295 offset += sizeDone;
296 return sizeDone;
297 } else {
298 return ERROR_END_OF_STREAM;
299 }
300 break;
301 }
302
303 case IStreamListener::DISCONTINUITY:
304 {
305 CHECK_EQ(size, 188u);
306 CHECK_EQ(sizeDone, 0u);
307
308 memset(data, 0, size);
309 sizeDone = size;
310 break;
311 }
312
313 default:
314 break;
Andreas Huber52b52cd2010-11-23 11:41:34 -0800315 }
Andreas Huberae9d5072010-12-06 10:36:06 -0800316
317 mQueue.erase(mQueue.begin());
318 continue;
Andreas Huber52b52cd2010-11-23 11:41:34 -0800319 }
320
Andreas Huber52b52cd2010-11-23 11:41:34 -0800321 size_t copy = size - sizeDone;
Andreas Huberae9d5072010-12-06 10:36:06 -0800322 if (copy > entry.mSize) {
323 copy = entry.mSize;
Andreas Huber52b52cd2010-11-23 11:41:34 -0800324 }
325
326 memcpy((uint8_t *)data + sizeDone,
Andreas Huberae9d5072010-12-06 10:36:06 -0800327 (const uint8_t *)mBuffers.itemAt(entry.mIndex)->pointer()
328 + entry.mOffset,
Andreas Huber52b52cd2010-11-23 11:41:34 -0800329 copy);
330
Andreas Huberae9d5072010-12-06 10:36:06 -0800331 entry.mSize -= copy;
332 entry.mOffset += copy;
Andreas Huber52b52cd2010-11-23 11:41:34 -0800333 sizeDone += copy;
334
Andreas Huberae9d5072010-12-06 10:36:06 -0800335 if (entry.mSize == 0) {
336 mSource->onBufferAvailable(entry.mIndex);
337 mQueue.erase(mQueue.begin());
Andreas Huber52b52cd2010-11-23 11:41:34 -0800338 }
339 }
340
341 mPosition += sizeDone;
342
343 return sizeDone;
344}
345
346void QueueDataSource::queueBuffer(size_t index, size_t size) {
347 Mutex::Autolock autoLock(mLock);
348
349 CHECK_LT(index, mBuffers.size());
350 CHECK_LE(size, mBuffers.itemAt(index)->size());
351
Andreas Huberae9d5072010-12-06 10:36:06 -0800352 QueueEntry entry;
353 entry.mIsCommand = false;
354 entry.mIndex = index;
355 entry.mSize = size;
356 entry.mOffset = 0;
Andreas Huber52b52cd2010-11-23 11:41:34 -0800357
Andreas Huberae9d5072010-12-06 10:36:06 -0800358 mQueue.push_back(entry);
Andreas Huber52b52cd2010-11-23 11:41:34 -0800359 mCondition.signal();
360}
361
Andreas Huberae9d5072010-12-06 10:36:06 -0800362void QueueDataSource::issueCommand(
363 IStreamListener::Command cmd,
364 bool synchronous,
365 const sp<AMessage> &msg) {
Andreas Huber52b52cd2010-11-23 11:41:34 -0800366 Mutex::Autolock autoLock(mLock);
367
Andreas Huberae9d5072010-12-06 10:36:06 -0800368 CHECK(!synchronous);
369
370 QueueEntry entry;
371 entry.mIsCommand = true;
372 entry.mCommand = cmd;
373 entry.mCommandMessage = msg;
374 mQueue.push_back(entry);
375
376 mCondition.signal();
Andreas Huber52b52cd2010-11-23 11:41:34 -0800377}
378
379void QueueListener::clearOwner() {
380 Mutex::Autolock autoLock(mLock);
381 mOwner = NULL;
382}
383
384void QueueListener::queueBuffer(size_t index, size_t size) {
385 Mutex::Autolock autoLock(mLock);
386 if (mOwner == NULL) {
387 return;
388 }
389 mOwner->queueBuffer(index, size);
390}
391
Andreas Huberae9d5072010-12-06 10:36:06 -0800392void QueueListener::issueCommand(
393 Command cmd, bool synchronous, const sp<AMessage> &msg) {
Andreas Huber52b52cd2010-11-23 11:41:34 -0800394 Mutex::Autolock autoLock(mLock);
395 if (mOwner == NULL) {
396 return;
397 }
Andreas Huberae9d5072010-12-06 10:36:06 -0800398 mOwner->issueCommand(cmd, synchronous, msg);
Andreas Huber52b52cd2010-11-23 11:41:34 -0800399}
400
401////////////////////////////////////////////////////////////////////////////////
402
Andreas Huber27366fc2009-11-20 09:32:46 -0800403AwesomePlayer::AwesomePlayer()
Andreas Huber406a18b2010-02-18 16:45:13 -0800404 : mQueueStarted(false),
405 mTimeSource(NULL),
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800406 mVideoRendererIsPreview(false),
Andreas Huber27366fc2009-11-20 09:32:46 -0800407 mAudioPlayer(NULL),
Andreas Huberffdf4782010-02-09 14:05:43 -0800408 mFlags(0),
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700409 mExtractorFlags(0),
Andreas Huberba7ec912010-02-12 10:42:02 -0800410 mVideoBuffer(NULL),
Gloria Wangd5770912010-06-22 13:55:38 -0700411 mDecryptHandle(NULL) {
Andreas Huber52b52cd2010-11-23 11:41:34 -0800412 CHECK_EQ(mClient.connect(), (status_t)OK);
Andreas Huber27366fc2009-11-20 09:32:46 -0800413
414 DataSource::RegisterDefaultSniffers();
415
Andreas Huber6be780e2010-02-08 14:40:30 -0800416 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
Andreas Huber27366fc2009-11-20 09:32:46 -0800417 mVideoEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800418 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
Andreas Huber27366fc2009-11-20 09:32:46 -0800419 mStreamDoneEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800420 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
Andreas Huberb9e63832010-01-26 16:20:10 -0800421 mBufferingEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800422
423 mCheckAudioStatusEvent = new AwesomeEvent(
424 this, &AwesomePlayer::onCheckAudioStatus);
425
Andreas Huber70d10c02010-02-03 11:37:29 -0800426 mAudioStatusEventPending = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800427
Andreas Huber27366fc2009-11-20 09:32:46 -0800428 reset();
429}
430
431AwesomePlayer::~AwesomePlayer() {
Andreas Huber406a18b2010-02-18 16:45:13 -0800432 if (mQueueStarted) {
433 mQueue.stop();
434 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800435
436 reset();
437
438 mClient.disconnect();
439}
440
Andreas Huberb9e63832010-01-26 16:20:10 -0800441void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800442 mQueue.cancelEvent(mVideoEvent->eventID());
443 mVideoEventPending = false;
444 mQueue.cancelEvent(mStreamDoneEvent->eventID());
445 mStreamDoneEventPending = false;
Andreas Huber70d10c02010-02-03 11:37:29 -0800446 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
447 mAudioStatusEventPending = false;
Andreas Huberb9e63832010-01-26 16:20:10 -0800448
449 if (!keepBufferingGoing) {
450 mQueue.cancelEvent(mBufferingEvent->eventID());
451 mBufferingEventPending = false;
452 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800453}
454
Andreas Hubera3f43842010-01-21 10:28:45 -0800455void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800456 Mutex::Autolock autoLock(mLock);
457 mListener = listener;
458}
459
Andreas Huber433c9ac2010-01-27 16:49:05 -0800460status_t AwesomePlayer::setDataSource(
461 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800462 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800463 return setDataSource_l(uri, headers);
464}
Andreas Huber27366fc2009-11-20 09:32:46 -0800465
Andreas Huberba7ec912010-02-12 10:42:02 -0800466status_t AwesomePlayer::setDataSource_l(
467 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800468 reset_l();
469
Andreas Huberffdf4782010-02-09 14:05:43 -0800470 mUri = uri;
Andreas Huberb9e63832010-01-26 16:20:10 -0800471
Andreas Huber6a1f5f92010-11-15 09:03:03 -0800472 if (!strncmp("http://", uri, 7)) {
473 // Hack to support http live.
474
475 size_t len = strlen(uri);
Andreas Huberb5c6afc2010-12-02 13:27:47 -0800476 if (!strcasecmp(&uri[len - 5], ".m3u8")
477 || strstr(&uri[7], "m3u8") != NULL) {
Andreas Huber6a1f5f92010-11-15 09:03:03 -0800478 mUri = "httplive://";
479 mUri.append(&uri[7]);
480 }
481 }
482
Andreas Huberffdf4782010-02-09 14:05:43 -0800483 if (headers) {
484 mUriHeaders = *headers;
Andreas Huberb9e63832010-01-26 16:20:10 -0800485 }
486
Andreas Huberffdf4782010-02-09 14:05:43 -0800487 // The actual work will be done during preparation in the call to
488 // ::finishSetDataSource_l to avoid blocking the calling thread in
489 // setDataSource for any significant time.
Andreas Huber27366fc2009-11-20 09:32:46 -0800490
Andreas Huberffdf4782010-02-09 14:05:43 -0800491 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800492}
493
494status_t AwesomePlayer::setDataSource(
495 int fd, int64_t offset, int64_t length) {
496 Mutex::Autolock autoLock(mLock);
497
498 reset_l();
499
Andreas Huberba7ec912010-02-12 10:42:02 -0800500 sp<DataSource> dataSource = new FileSource(fd, offset, length);
Andreas Huber27366fc2009-11-20 09:32:46 -0800501
Andreas Huberba7ec912010-02-12 10:42:02 -0800502 status_t err = dataSource->initCheck();
Andreas Huber27366fc2009-11-20 09:32:46 -0800503
504 if (err != OK) {
505 return err;
506 }
507
Andreas Huberba7ec912010-02-12 10:42:02 -0800508 mFileSource = dataSource;
509
510 return setDataSource_l(dataSource);
511}
512
Andreas Huber52b52cd2010-11-23 11:41:34 -0800513status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) {
514 Mutex::Autolock autoLock(mLock);
515
516 reset_l();
517
518 sp<DataSource> dataSource = new QueueDataSource(source);
Andreas Huberae9d5072010-12-06 10:36:06 -0800519 sp<MediaExtractor> extractor = new MPEG2TSExtractor(dataSource);
Andreas Huber52b52cd2010-11-23 11:41:34 -0800520
521 return setDataSource_l(extractor);
Andreas Huber52b52cd2010-11-23 11:41:34 -0800522}
523
Andreas Huberba7ec912010-02-12 10:42:02 -0800524status_t AwesomePlayer::setDataSource_l(
525 const sp<DataSource> &dataSource) {
526 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
Andreas Huber27366fc2009-11-20 09:32:46 -0800527
528 if (extractor == NULL) {
529 return UNKNOWN_ERROR;
530 }
531
Gloria Wangd5770912010-06-22 13:55:38 -0700532 dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
Gloria Wangeab18ea2010-10-29 10:09:47 -0700533 if (mDecryptHandle != NULL
534 && RightsStatus::RIGHTS_VALID != mDecryptHandle->status) {
535 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
Gloria Wangd5770912010-06-22 13:55:38 -0700536 }
537
Andreas Huber27366fc2009-11-20 09:32:46 -0800538 return setDataSource_l(extractor);
539}
540
541status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700542 // Attempt to approximate overall stream bitrate by summing all
543 // tracks' individual bitrates, if not all of them advertise bitrate,
544 // we have to fail.
545
546 int64_t totalBitRate = 0;
547
548 for (size_t i = 0; i < extractor->countTracks(); ++i) {
549 sp<MetaData> meta = extractor->getTrackMetaData(i);
550
551 int32_t bitrate;
552 if (!meta->findInt32(kKeyBitRate, &bitrate)) {
553 totalBitRate = -1;
554 break;
555 }
556
557 totalBitRate += bitrate;
558 }
559
560 mBitrate = totalBitRate;
561
562 LOGV("mBitrate = %lld bits/sec", mBitrate);
563
Andreas Huber27366fc2009-11-20 09:32:46 -0800564 bool haveAudio = false;
565 bool haveVideo = false;
566 for (size_t i = 0; i < extractor->countTracks(); ++i) {
567 sp<MetaData> meta = extractor->getTrackMetaData(i);
568
569 const char *mime;
570 CHECK(meta->findCString(kKeyMIMEType, &mime));
571
572 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800573 setVideoSource(extractor->getTrack(i));
574 haveVideo = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800575 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800576 setAudioSource(extractor->getTrack(i));
577 haveAudio = true;
Andreas Huber9fee0b22010-09-03 14:09:21 -0700578
Andreas Huber1913c1a2010-10-04 11:09:31 -0700579 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
580 // Only do this for vorbis audio, none of the other audio
581 // formats even support this ringtone specific hack and
582 // retrieving the metadata on some extractors may turn out
583 // to be very expensive.
584 sp<MetaData> fileMeta = extractor->getMetaData();
585 int32_t loop;
586 if (fileMeta != NULL
587 && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
588 mFlags |= AUTO_LOOPING;
589 }
Andreas Huber9fee0b22010-09-03 14:09:21 -0700590 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800591 }
592
593 if (haveAudio && haveVideo) {
594 break;
595 }
596 }
597
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700598 if (!haveAudio && !haveVideo) {
599 return UNKNOWN_ERROR;
600 }
601
602 mExtractorFlags = extractor->flags();
603
604 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800605}
606
607void AwesomePlayer::reset() {
608 Mutex::Autolock autoLock(mLock);
609 reset_l();
610}
611
612void AwesomePlayer::reset_l() {
Gloria Wangd5770912010-06-22 13:55:38 -0700613 if (mDecryptHandle != NULL) {
614 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
615 Playback::STOP, 0);
Gloria Wangc2c22e72010-11-01 15:53:16 -0700616 mDrmManagerClient->closeDecryptSession(mDecryptHandle);
Gloria Wangd5770912010-06-22 13:55:38 -0700617 mDecryptHandle = NULL;
618 mDrmManagerClient = NULL;
619 }
620
Andreas Huberedbb4d82010-03-12 08:59:22 -0800621 if (mFlags & PREPARING) {
622 mFlags |= PREPARE_CANCELLED;
623 if (mConnectingDataSource != NULL) {
624 LOGI("interrupting the connection process");
625 mConnectingDataSource->disconnect();
626 }
Andreas Hubereaf2c5a2010-10-19 12:18:51 -0700627
628 if (mFlags & PREPARING_CONNECTED) {
629 // We are basically done preparing, we're just buffering
630 // enough data to start playback, we can safely interrupt that.
631 finishAsyncPrepare_l();
632 }
Andreas Huberedbb4d82010-03-12 08:59:22 -0800633 }
634
Andreas Huberffdf4782010-02-09 14:05:43 -0800635 while (mFlags & PREPARING) {
636 mPreparedCondition.wait(mLock);
637 }
638
Andreas Huber27366fc2009-11-20 09:32:46 -0800639 cancelPlayerEvents();
640
Andreas Huber4d61f602010-06-10 11:17:50 -0700641 mCachedSource.clear();
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800642 mAudioTrack.clear();
643 mVideoTrack.clear();
644
Andreas Huberba7ec912010-02-12 10:42:02 -0800645 // Shutdown audio first, so that the respone to the reset request
646 // appears to happen instantaneously as far as the user is concerned
647 // If we did this later, audio would continue playing while we
648 // shutdown the video-related resources and the player appear to
649 // not be as responsive to a reset request.
Andreas Huberedbb4d82010-03-12 08:59:22 -0800650 if (mAudioPlayer == NULL && mAudioSource != NULL) {
651 // If we had an audio player, it would have effectively
652 // taken possession of the audio source and stopped it when
653 // _it_ is stopped. Otherwise this is still our responsibility.
654 mAudioSource->stop();
655 }
Andreas Huberba7ec912010-02-12 10:42:02 -0800656 mAudioSource.clear();
657
Andreas Huberba7ec912010-02-12 10:42:02 -0800658 mTimeSource = NULL;
659
660 delete mAudioPlayer;
661 mAudioPlayer = NULL;
662
Andreas Huber3522b5a52010-01-22 14:36:53 -0800663 mVideoRenderer.clear();
664
Andreas Huber27366fc2009-11-20 09:32:46 -0800665 if (mVideoBuffer) {
666 mVideoBuffer->release();
667 mVideoBuffer = NULL;
668 }
669
Andreas Hubere0dd7d32010-08-24 14:33:58 -0700670 if (mRTSPController != NULL) {
671 mRTSPController->disconnect();
672 mRTSPController.clear();
673 }
674
Andreas Huberb5590842010-12-03 16:12:25 -0800675 if (mLiveSession != NULL) {
676 mLiveSession->disconnect();
677 mLiveSession.clear();
678 }
679
Andreas Huber57648e42010-08-04 10:14:30 -0700680 mRTPPusher.clear();
681 mRTCPPusher.clear();
682 mRTPSession.clear();
Andreas Huber7a747b82010-06-07 15:19:40 -0700683
Andreas Huber27366fc2009-11-20 09:32:46 -0800684 if (mVideoSource != NULL) {
685 mVideoSource->stop();
Andreas Huber98b48de2010-01-29 10:10:22 -0800686
687 // The following hack is necessary to ensure that the OMX
688 // component is completely released by the time we may try
689 // to instantiate it again.
690 wp<MediaSource> tmp = mVideoSource;
Andreas Huber27366fc2009-11-20 09:32:46 -0800691 mVideoSource.clear();
Andreas Huber98b48de2010-01-29 10:10:22 -0800692 while (tmp.promote() != NULL) {
693 usleep(1000);
694 }
695 IPCThreadState::self()->flushCommands();
Andreas Huber27366fc2009-11-20 09:32:46 -0800696 }
697
Andreas Huber27366fc2009-11-20 09:32:46 -0800698 mDurationUs = -1;
699 mFlags = 0;
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700700 mExtractorFlags = 0;
Andreas Huber27366fc2009-11-20 09:32:46 -0800701 mTimeSourceDeltaUs = 0;
702 mVideoTimeUs = 0;
703
704 mSeeking = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700705 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800706 mSeekTimeUs = 0;
Andreas Huberb9e63832010-01-26 16:20:10 -0800707
Andreas Huberffdf4782010-02-09 14:05:43 -0800708 mUri.setTo("");
709 mUriHeaders.clear();
Andreas Huberba7ec912010-02-12 10:42:02 -0800710
711 mFileSource.clear();
712
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700713 mBitrate = -1;
Andreas Huber27366fc2009-11-20 09:32:46 -0800714}
715
Andreas Huber6be780e2010-02-08 14:40:30 -0800716void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
Andreas Hubera3f43842010-01-21 10:28:45 -0800717 if (mListener != NULL) {
718 sp<MediaPlayerBase> listener = mListener.promote();
719
720 if (listener != NULL) {
Andreas Huber6be780e2010-02-08 14:40:30 -0800721 listener->sendEvent(msg, ext1, ext2);
Andreas Hubera3f43842010-01-21 10:28:45 -0800722 }
723 }
724}
725
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700726bool AwesomePlayer::getBitrate(int64_t *bitrate) {
James Dongb1262a82010-11-16 14:04:54 -0800727 off64_t size;
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700728 if (mDurationUs >= 0 && mCachedSource != NULL
729 && mCachedSource->getSize(&size) == OK) {
730 *bitrate = size * 8000000ll / mDurationUs; // in bits/sec
731 return true;
732 }
733
734 if (mBitrate >= 0) {
735 *bitrate = mBitrate;
736 return true;
737 }
738
739 *bitrate = 0;
740
741 return false;
742}
743
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700744// Returns true iff cached duration is available/applicable.
745bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700746 int64_t bitrate;
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700747
748 if (mRTSPController != NULL) {
749 *durationUs = mRTSPController->getQueueDurationUs(eos);
750 return true;
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700751 } else if (mCachedSource != NULL && getBitrate(&bitrate)) {
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700752 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(eos);
753 *durationUs = cachedDataRemaining * 8000000ll / bitrate;
754 return true;
755 }
756
757 return false;
758}
759
Andreas Huber10b920c2010-11-11 15:37:17 -0800760void AwesomePlayer::ensureCacheIsFetching_l() {
761 if (mCachedSource != NULL) {
762 mCachedSource->resumeFetchingIfNecessary();
763 }
764}
765
Andreas Huberb9e63832010-01-26 16:20:10 -0800766void AwesomePlayer::onBufferingUpdate() {
767 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800768 if (!mBufferingEventPending) {
769 return;
770 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800771 mBufferingEventPending = false;
772
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700773 if (mCachedSource != NULL) {
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700774 bool eos;
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700775 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&eos);
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700776
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700777 if (eos) {
778 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
Andreas Huber05f67872010-10-04 11:36:39 -0700779 if (mFlags & PREPARING) {
780 LOGV("cache has reached EOS, prepare is done.");
781 finishAsyncPrepare_l();
782 }
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700783 } else {
Andreas Huber4deb3eb2010-10-12 16:55:11 -0700784 int64_t bitrate;
785 if (getBitrate(&bitrate)) {
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700786 size_t cachedSize = mCachedSource->cachedSize();
787 int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
788
789 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
790 if (percentage > 100) {
791 percentage = 100;
792 }
793
794 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
795 } else {
796 // We don't know the bitrate of the stream, use absolute size
797 // limits to maintain the cache.
798
Andreas Huber54d09722010-10-12 11:34:37 -0700799 const size_t kLowWaterMarkBytes = 40000;
800 const size_t kHighWaterMarkBytes = 200000;
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700801
802 if ((mFlags & PLAYING) && !eos
803 && (cachedDataRemaining < kLowWaterMarkBytes)) {
804 LOGI("cache is running low (< %d) , pausing.",
805 kLowWaterMarkBytes);
806 mFlags |= CACHE_UNDERRUN;
807 pause_l();
Andreas Huber10b920c2010-11-11 15:37:17 -0800808 ensureCacheIsFetching_l();
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700809 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
810 } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
811 if (mFlags & CACHE_UNDERRUN) {
812 LOGI("cache has filled up (> %d), resuming.",
813 kHighWaterMarkBytes);
814 mFlags &= ~CACHE_UNDERRUN;
815 play_l();
816 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
817 } else if (mFlags & PREPARING) {
818 LOGV("cache has filled up (> %d), prepare is done",
819 kHighWaterMarkBytes);
820 finishAsyncPrepare_l();
821 }
822 }
823 }
824 }
825 }
826
827 int64_t cachedDurationUs;
828 bool eos;
829 if (getCachedDuration_l(&cachedDurationUs, &eos)) {
Andreas Huber10b920c2010-11-11 15:37:17 -0800830 LOGV("cachedDurationUs = %.2f secs, eos=%d",
831 cachedDurationUs / 1E6, eos);
832
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700833 if ((mFlags & PLAYING) && !eos
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700834 && (cachedDurationUs < kLowWaterMarkUs)) {
835 LOGI("cache is running low (%.2f secs) , pausing.",
836 cachedDurationUs / 1E6);
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700837 mFlags |= CACHE_UNDERRUN;
838 pause_l();
Andreas Huber10b920c2010-11-11 15:37:17 -0800839 ensureCacheIsFetching_l();
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700840 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700841 } else if (eos || cachedDurationUs > kHighWaterMarkUs) {
842 if (mFlags & CACHE_UNDERRUN) {
843 LOGI("cache has filled up (%.2f secs), resuming.",
844 cachedDurationUs / 1E6);
845 mFlags &= ~CACHE_UNDERRUN;
846 play_l();
847 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
848 } else if (mFlags & PREPARING) {
849 LOGV("cache has filled up (%.2f secs), prepare is done",
850 cachedDurationUs / 1E6);
851 finishAsyncPrepare_l();
Andreas Huberc23296e2010-08-25 12:31:48 -0700852 }
Andreas Huberc23296e2010-08-25 12:31:48 -0700853 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800854 }
Andreas Huber4d61f602010-06-10 11:17:50 -0700855
Andreas Huber4d61f602010-06-10 11:17:50 -0700856 postBufferingEvent_l();
Andreas Huberb9e63832010-01-26 16:20:10 -0800857}
858
Andreas Huber4c19bf92010-09-08 14:32:20 -0700859void AwesomePlayer::partial_reset_l() {
860 // Only reset the video renderer and shut down the video decoder.
861 // Then instantiate a new video decoder and resume video playback.
862
863 mVideoRenderer.clear();
864
Andreas Huber4c19bf92010-09-08 14:32:20 -0700865 if (mVideoBuffer) {
866 mVideoBuffer->release();
867 mVideoBuffer = NULL;
868 }
869
870 {
871 mVideoSource->stop();
872
873 // The following hack is necessary to ensure that the OMX
874 // component is completely released by the time we may try
875 // to instantiate it again.
876 wp<MediaSource> tmp = mVideoSource;
877 mVideoSource.clear();
878 while (tmp.promote() != NULL) {
879 usleep(1000);
880 }
881 IPCThreadState::self()->flushCommands();
882 }
883
Andreas Huber52b52cd2010-11-23 11:41:34 -0800884 CHECK_EQ((status_t)OK,
885 initVideoDecoder(OMXCodec::kIgnoreCodecSpecificData));
Andreas Huber4c19bf92010-09-08 14:32:20 -0700886}
887
Andreas Huber27366fc2009-11-20 09:32:46 -0800888void AwesomePlayer::onStreamDone() {
889 // Posted whenever any stream finishes playing.
890
891 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800892 if (!mStreamDoneEventPending) {
893 return;
894 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800895 mStreamDoneEventPending = false;
896
Andreas Huber4c19bf92010-09-08 14:32:20 -0700897 if (mStreamDoneStatus == INFO_DISCONTINUITY) {
898 // This special status is returned because an http live stream's
899 // video stream switched to a different bandwidth at this point
900 // and future data may have been encoded using different parameters.
901 // This requires us to shutdown the video decoder and reinstantiate
902 // a fresh one.
903
904 LOGV("INFO_DISCONTINUITY");
905
906 CHECK(mVideoSource != NULL);
907
908 partial_reset_l();
909 postVideoEvent_l();
910 return;
911 } else if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
Andreas Huber971305d2010-07-07 13:35:27 -0700912 LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
913
914 notifyListener_l(
915 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
916
Andreas Huberc743f452010-10-05 10:25:34 -0700917 pause_l(true /* at eos */);
Andreas Huber971305d2010-07-07 13:35:27 -0700918
919 mFlags |= AT_EOS;
920 return;
921 }
922
923 const bool allDone =
924 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
925 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
926
927 if (!allDone) {
928 return;
929 }
930
Andreas Huber9fee0b22010-09-03 14:09:21 -0700931 if (mFlags & (LOOPING | AUTO_LOOPING)) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800932 seekTo_l(0);
933
Andreas Huber7085b6842010-02-03 16:02:02 -0800934 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800935 postVideoEvent_l();
936 }
937 } else {
Andreas Huber971305d2010-07-07 13:35:27 -0700938 LOGV("MEDIA_PLAYBACK_COMPLETE");
939 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800940
Andreas Huberc743f452010-10-05 10:25:34 -0700941 pause_l(true /* at eos */);
Andreas Huber406a18b2010-02-18 16:45:13 -0800942
943 mFlags |= AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800944 }
945}
946
947status_t AwesomePlayer::play() {
948 Mutex::Autolock autoLock(mLock);
Andreas Huber4d61f602010-06-10 11:17:50 -0700949
950 mFlags &= ~CACHE_UNDERRUN;
951
Andreas Huberba7ec912010-02-12 10:42:02 -0800952 return play_l();
953}
Andreas Huber27366fc2009-11-20 09:32:46 -0800954
Andreas Huberba7ec912010-02-12 10:42:02 -0800955status_t AwesomePlayer::play_l() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800956 if (mFlags & PLAYING) {
957 return OK;
958 }
959
Andreas Huberffdf4782010-02-09 14:05:43 -0800960 if (!(mFlags & PREPARED)) {
961 status_t err = prepare_l();
962
963 if (err != OK) {
964 return err;
965 }
966 }
967
Andreas Huber27366fc2009-11-20 09:32:46 -0800968 mFlags |= PLAYING;
969 mFlags |= FIRST_FRAME;
970
Andreas Huberc1d5c922009-12-10 15:49:04 -0800971 bool deferredAudioSeek = false;
972
Gloria Wang95dbffb2010-11-04 17:38:39 -0700973 if (mDecryptHandle != NULL) {
974 int64_t position;
975 getPosition(&position);
976 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
977 Playback::START, position / 1000);
978 }
979
Andreas Huber27366fc2009-11-20 09:32:46 -0800980 if (mAudioSource != NULL) {
981 if (mAudioPlayer == NULL) {
982 if (mAudioSink != NULL) {
Andreas Huber2b359ed2010-09-28 11:56:39 -0700983 mAudioPlayer = new AudioPlayer(mAudioSink, this);
Andreas Huber27366fc2009-11-20 09:32:46 -0800984 mAudioPlayer->setSource(mAudioSource);
Andreas Huberdc9927d2010-03-08 15:46:13 -0800985
986 // We've already started the MediaSource in order to enable
987 // the prefetcher to read its data.
988 status_t err = mAudioPlayer->start(
989 true /* sourceAlreadyStarted */);
Andreas Huber62eac002010-01-29 13:24:58 -0800990
991 if (err != OK) {
992 delete mAudioPlayer;
993 mAudioPlayer = NULL;
994
995 mFlags &= ~(PLAYING | FIRST_FRAME);
996
Gloria Wang95dbffb2010-11-04 17:38:39 -0700997 if (mDecryptHandle != NULL) {
998 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
999 Playback::STOP, 0);
1000 }
1001
Andreas Huber62eac002010-01-29 13:24:58 -08001002 return err;
1003 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001004
Andreas Huber27366fc2009-11-20 09:32:46 -08001005 mTimeSource = mAudioPlayer;
1006
Andreas Huberc1d5c922009-12-10 15:49:04 -08001007 deferredAudioSeek = true;
Andreas Huber70d10c02010-02-03 11:37:29 -08001008
1009 mWatchForAudioSeekComplete = false;
1010 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -08001011 }
1012 } else {
1013 mAudioPlayer->resume();
1014 }
1015 }
1016
1017 if (mTimeSource == NULL && mAudioPlayer == NULL) {
Andreas Huber971305d2010-07-07 13:35:27 -07001018 mTimeSource = &mSystemTimeSource;
Andreas Huber27366fc2009-11-20 09:32:46 -08001019 }
1020
1021 if (mVideoSource != NULL) {
Andreas Huber7085b6842010-02-03 16:02:02 -08001022 // Kick off video playback
1023 postVideoEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -08001024 }
1025
Andreas Huberc1d5c922009-12-10 15:49:04 -08001026 if (deferredAudioSeek) {
1027 // If there was a seek request while we were paused
1028 // and we're just starting up again, honor the request now.
1029 seekAudioIfNecessary_l();
1030 }
1031
Andreas Huber406a18b2010-02-18 16:45:13 -08001032 if (mFlags & AT_EOS) {
1033 // Legacy behaviour, if a stream finishes playing and then
1034 // is started again, we play from the start...
1035 seekTo_l(0);
1036 }
1037
Andreas Huber27366fc2009-11-20 09:32:46 -08001038 return OK;
1039}
1040
Andreas Hubere3c01832010-08-16 08:49:37 -07001041void AwesomePlayer::notifyVideoSize_l() {
1042 sp<MetaData> meta = mVideoSource->getFormat();
1043
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001044 int32_t cropLeft, cropTop, cropRight, cropBottom;
1045 if (!meta->findRect(
1046 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
1047 int32_t width, height;
1048 CHECK(meta->findInt32(kKeyWidth, &width));
1049 CHECK(meta->findInt32(kKeyHeight, &height));
1050
1051 cropLeft = cropTop = 0;
1052 cropRight = width - 1;
1053 cropBottom = height - 1;
1054
1055 LOGV("got dimensions only %d x %d", width, height);
1056 } else {
1057 LOGV("got crop rect %d, %d, %d, %d",
1058 cropLeft, cropTop, cropRight, cropBottom);
1059 }
1060
1061 int32_t usableWidth = cropRight - cropLeft + 1;
1062 int32_t usableHeight = cropBottom - cropTop + 1;
Andreas Hubere3c01832010-08-16 08:49:37 -07001063
Andreas Huber940c8662010-11-16 15:26:30 -08001064 int32_t rotationDegrees;
1065 if (!mVideoTrack->getFormat()->findInt32(
1066 kKeyRotation, &rotationDegrees)) {
1067 rotationDegrees = 0;
1068 }
1069
1070 if (rotationDegrees == 90 || rotationDegrees == 270) {
1071 notifyListener_l(
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001072 MEDIA_SET_VIDEO_SIZE, usableHeight, usableWidth);
Andreas Huber940c8662010-11-16 15:26:30 -08001073 } else {
1074 notifyListener_l(
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001075 MEDIA_SET_VIDEO_SIZE, usableWidth, usableHeight);
Andreas Huber940c8662010-11-16 15:26:30 -08001076 }
Andreas Hubere3c01832010-08-16 08:49:37 -07001077}
1078
Andreas Huber27366fc2009-11-20 09:32:46 -08001079void AwesomePlayer::initRenderer_l() {
Andreas Huberc23dabf2010-11-16 13:05:53 -08001080 if (mSurface == NULL) {
1081 return;
1082 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001083
Andreas Huberc23dabf2010-11-16 13:05:53 -08001084 sp<MetaData> meta = mVideoSource->getFormat();
Andreas Huber27366fc2009-11-20 09:32:46 -08001085
Andreas Huberc23dabf2010-11-16 13:05:53 -08001086 int32_t format;
1087 const char *component;
1088 int32_t decodedWidth, decodedHeight;
1089 CHECK(meta->findInt32(kKeyColorFormat, &format));
1090 CHECK(meta->findCString(kKeyDecoderComponent, &component));
1091 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
1092 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
Andreas Hubera67d5382009-12-10 15:32:12 -08001093
Andreas Huber940c8662010-11-16 15:26:30 -08001094 int32_t rotationDegrees;
1095 if (!mVideoTrack->getFormat()->findInt32(
1096 kKeyRotation, &rotationDegrees)) {
1097 rotationDegrees = 0;
1098 }
1099
Andreas Huberc23dabf2010-11-16 13:05:53 -08001100 mVideoRenderer.clear();
Andreas Hubera67d5382009-12-10 15:32:12 -08001101
Andreas Huberc23dabf2010-11-16 13:05:53 -08001102 // Must ensure that mVideoRenderer's destructor is actually executed
1103 // before creating a new one.
1104 IPCThreadState::self()->flushCommands();
1105
1106 if (USE_SURFACE_ALLOC && strncmp(component, "OMX.", 4) == 0) {
1107 // Hardware decoders avoid the CPU color conversion by decoding
1108 // directly to ANativeBuffers, so we must use a renderer that
1109 // just pushes those buffers to the ANativeWindow.
Andreas Huber940c8662010-11-16 15:26:30 -08001110 mVideoRenderer =
1111 new AwesomeNativeWindowRenderer(mSurface, rotationDegrees);
Andreas Huberc23dabf2010-11-16 13:05:53 -08001112 } else {
1113 // Other decoders are instantiated locally and as a consequence
1114 // allocate their buffers in local address space. This renderer
1115 // then performs a color conversion and copy to get the data
1116 // into the ANativeBuffer.
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001117 mVideoRenderer = new AwesomeLocalRenderer(mSurface, meta);
Andreas Huber27366fc2009-11-20 09:32:46 -08001118 }
1119}
1120
1121status_t AwesomePlayer::pause() {
1122 Mutex::Autolock autoLock(mLock);
Andreas Huber4d61f602010-06-10 11:17:50 -07001123
1124 mFlags &= ~CACHE_UNDERRUN;
1125
Andreas Huber27366fc2009-11-20 09:32:46 -08001126 return pause_l();
1127}
1128
Andreas Huberc743f452010-10-05 10:25:34 -07001129status_t AwesomePlayer::pause_l(bool at_eos) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001130 if (!(mFlags & PLAYING)) {
1131 return OK;
1132 }
1133
Andreas Huberb9e63832010-01-26 16:20:10 -08001134 cancelPlayerEvents(true /* keepBufferingGoing */);
Andreas Huber27366fc2009-11-20 09:32:46 -08001135
1136 if (mAudioPlayer != NULL) {
Andreas Huberc743f452010-10-05 10:25:34 -07001137 if (at_eos) {
1138 // If we played the audio stream to completion we
1139 // want to make sure that all samples remaining in the audio
1140 // track's queue are played out.
1141 mAudioPlayer->pause(true /* playPendingSamples */);
1142 } else {
1143 mAudioPlayer->pause();
1144 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001145 }
1146
1147 mFlags &= ~PLAYING;
1148
Gloria Wangd5770912010-06-22 13:55:38 -07001149 if (mDecryptHandle != NULL) {
1150 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1151 Playback::PAUSE, 0);
1152 }
1153
Andreas Huber27366fc2009-11-20 09:32:46 -08001154 return OK;
1155}
1156
1157bool AwesomePlayer::isPlaying() const {
Andreas Huber4d61f602010-06-10 11:17:50 -07001158 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
Andreas Huber27366fc2009-11-20 09:32:46 -08001159}
1160
Andreas Hubere3c01832010-08-16 08:49:37 -07001161void AwesomePlayer::setSurface(const sp<Surface> &surface) {
1162 Mutex::Autolock autoLock(mLock);
1163
1164 mSurface = surface;
1165}
1166
Andreas Huber27366fc2009-11-20 09:32:46 -08001167void AwesomePlayer::setAudioSink(
1168 const sp<MediaPlayerBase::AudioSink> &audioSink) {
1169 Mutex::Autolock autoLock(mLock);
1170
1171 mAudioSink = audioSink;
1172}
1173
1174status_t AwesomePlayer::setLooping(bool shouldLoop) {
1175 Mutex::Autolock autoLock(mLock);
1176
1177 mFlags = mFlags & ~LOOPING;
1178
1179 if (shouldLoop) {
1180 mFlags |= LOOPING;
1181 }
1182
1183 return OK;
1184}
1185
1186status_t AwesomePlayer::getDuration(int64_t *durationUs) {
Andreas Huber252573c2010-03-26 10:17:17 -07001187 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001188
1189 if (mDurationUs < 0) {
1190 return UNKNOWN_ERROR;
1191 }
1192
1193 *durationUs = mDurationUs;
1194
1195 return OK;
1196}
1197
1198status_t AwesomePlayer::getPosition(int64_t *positionUs) {
Andreas Hubereeb97d92010-08-27 13:29:08 -07001199 if (mRTSPController != NULL) {
1200 *positionUs = mRTSPController->getNormalPlayTimeUs();
1201 }
1202 else if (mSeeking) {
Andreas Huberddb709c2010-04-07 10:24:35 -07001203 *positionUs = mSeekTimeUs;
1204 } else if (mVideoSource != NULL) {
Andreas Huber252573c2010-03-26 10:17:17 -07001205 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001206 *positionUs = mVideoTimeUs;
1207 } else if (mAudioPlayer != NULL) {
1208 *positionUs = mAudioPlayer->getMediaTimeUs();
1209 } else {
1210 *positionUs = 0;
1211 }
1212
1213 return OK;
1214}
1215
1216status_t AwesomePlayer::seekTo(int64_t timeUs) {
Andreas Huber10b9b3f2010-10-08 10:16:24 -07001217 if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
Andreas Huber62f7ffe2010-05-06 10:18:05 -07001218 Mutex::Autolock autoLock(mLock);
1219 return seekTo_l(timeUs);
1220 }
1221
1222 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -08001223}
1224
Andreas Huber0c46b692010-10-08 15:21:08 -07001225// static
1226void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) {
1227 static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone();
1228}
1229
1230void AwesomePlayer::onRTSPSeekDone() {
1231 notifyListener_l(MEDIA_SEEK_COMPLETE);
1232 mSeekNotificationSent = true;
1233}
1234
Andreas Huber27366fc2009-11-20 09:32:46 -08001235status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
Andreas Hubere0dd7d32010-08-24 14:33:58 -07001236 if (mRTSPController != NULL) {
Andreas Huber0c46b692010-10-08 15:21:08 -07001237 mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this);
Andreas Hubere0dd7d32010-08-24 14:33:58 -07001238 return OK;
1239 }
1240
Andreas Huber4d61f602010-06-10 11:17:50 -07001241 if (mFlags & CACHE_UNDERRUN) {
1242 mFlags &= ~CACHE_UNDERRUN;
1243 play_l();
1244 }
1245
Andreas Huber27366fc2009-11-20 09:32:46 -08001246 mSeeking = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001247 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -08001248 mSeekTimeUs = timeUs;
Andreas Huber971305d2010-07-07 13:35:27 -07001249 mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
Andreas Huber27366fc2009-11-20 09:32:46 -08001250
1251 seekAudioIfNecessary_l();
1252
Andreas Huber8e2b9412010-03-31 09:40:15 -07001253 if (!(mFlags & PLAYING)) {
1254 LOGV("seeking while paused, sending SEEK_COMPLETE notification"
1255 " immediately.");
1256
1257 notifyListener_l(MEDIA_SEEK_COMPLETE);
1258 mSeekNotificationSent = true;
1259 }
1260
Andreas Huber27366fc2009-11-20 09:32:46 -08001261 return OK;
1262}
1263
1264void AwesomePlayer::seekAudioIfNecessary_l() {
Andreas Huber7085b6842010-02-03 16:02:02 -08001265 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001266 mAudioPlayer->seekTo(mSeekTimeUs);
1267
Andreas Huber70d10c02010-02-03 11:37:29 -08001268 mWatchForAudioSeekComplete = true;
1269 mWatchForAudioEOS = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001270 mSeekNotificationSent = false;
Gloria Wangd5770912010-06-22 13:55:38 -07001271
1272 if (mDecryptHandle != NULL) {
1273 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1274 Playback::PAUSE, 0);
1275 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1276 Playback::START, mSeekTimeUs / 1000);
1277 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001278 }
1279}
1280
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001281void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
1282 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001283
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001284 mAudioTrack = source;
1285}
1286
1287status_t AwesomePlayer::initAudioDecoder() {
1288 sp<MetaData> meta = mAudioTrack->getFormat();
Andreas Huberc79827a2010-01-05 10:54:55 -08001289
1290 const char *mime;
1291 CHECK(meta->findCString(kKeyMIMEType, &mime));
1292
1293 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001294 mAudioSource = mAudioTrack;
Andreas Huberc79827a2010-01-05 10:54:55 -08001295 } else {
1296 mAudioSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001297 mClient.interface(), mAudioTrack->getFormat(),
Andreas Huberc79827a2010-01-05 10:54:55 -08001298 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001299 mAudioTrack);
Andreas Huberc79827a2010-01-05 10:54:55 -08001300 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001301
1302 if (mAudioSource != NULL) {
1303 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001304 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -07001305 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001306 if (mDurationUs < 0 || durationUs > mDurationUs) {
1307 mDurationUs = durationUs;
1308 }
1309 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001310
Andreas Huber3c78a1b2010-05-13 09:15:21 -07001311 status_t err = mAudioSource->start();
1312
1313 if (err != OK) {
1314 mAudioSource.clear();
1315 return err;
1316 }
Andreas Huberd0332ad2010-04-12 16:05:57 -07001317 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
1318 // For legacy reasons we're simply going to ignore the absence
1319 // of an audio decoder for QCELP instead of aborting playback
1320 // altogether.
1321 return OK;
1322 }
Andreas Huberdc9927d2010-03-08 15:46:13 -08001323
Andreas Huber27366fc2009-11-20 09:32:46 -08001324 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
1325}
1326
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001327void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
1328 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001329
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001330 mVideoTrack = source;
1331}
1332
Andreas Huber4c19bf92010-09-08 14:32:20 -07001333status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001334 mVideoSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001335 mClient.interface(), mVideoTrack->getFormat(),
Andreas Huber27366fc2009-11-20 09:32:46 -08001336 false, // createEncoder
Andreas Huber57648e42010-08-04 10:14:30 -07001337 mVideoTrack,
Andreas Huber6a1f5f92010-11-15 09:03:03 -08001338 NULL, flags, USE_SURFACE_ALLOC ? mSurface : NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001339
1340 if (mVideoSource != NULL) {
1341 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001342 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -07001343 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -08001344 if (mDurationUs < 0 || durationUs > mDurationUs) {
1345 mDurationUs = durationUs;
1346 }
1347 }
1348
Andreas Huber1919e5a2010-05-20 10:37:06 -07001349 status_t err = mVideoSource->start();
1350
1351 if (err != OK) {
1352 mVideoSource.clear();
1353 return err;
1354 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001355 }
1356
1357 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
1358}
1359
Andreas Huber4d450a82010-10-19 09:34:44 -07001360void AwesomePlayer::finishSeekIfNecessary(int64_t videoTimeUs) {
1361 if (!mSeeking) {
1362 return;
1363 }
1364
1365 if (mAudioPlayer != NULL) {
Jamie Gennis6913c612010-10-20 15:55:43 -07001366 LOGV("seeking audio to %lld us (%.2f secs).", videoTimeUs, videoTimeUs / 1E6);
Andreas Huber4d450a82010-10-19 09:34:44 -07001367
1368 // If we don't have a video time, seek audio to the originally
1369 // requested seek time instead.
1370
1371 mAudioPlayer->seekTo(videoTimeUs < 0 ? mSeekTimeUs : videoTimeUs);
1372 mAudioPlayer->resume();
1373 mWatchForAudioSeekComplete = true;
1374 mWatchForAudioEOS = true;
1375 } else if (!mSeekNotificationSent) {
1376 // If we're playing video only, report seek complete now,
1377 // otherwise audio player will notify us later.
1378 notifyListener_l(MEDIA_SEEK_COMPLETE);
1379 }
1380
1381 mFlags |= FIRST_FRAME;
1382 mSeeking = false;
1383 mSeekNotificationSent = false;
Gloria Wang3f9a8192010-10-29 14:50:17 -07001384
1385 if (mDecryptHandle != NULL) {
1386 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1387 Playback::PAUSE, 0);
1388 mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
1389 Playback::START, videoTimeUs / 1000);
1390 }
Andreas Huber4d450a82010-10-19 09:34:44 -07001391}
1392
Andreas Huber6be780e2010-02-08 14:40:30 -08001393void AwesomePlayer::onVideoEvent() {
Andreas Huber27366fc2009-11-20 09:32:46 -08001394 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -08001395 if (!mVideoEventPending) {
1396 // The event has been cancelled in reset_l() but had already
1397 // been scheduled for execution at that time.
1398 return;
1399 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001400 mVideoEventPending = false;
1401
1402 if (mSeeking) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001403 if (mVideoBuffer) {
1404 mVideoBuffer->release();
1405 mVideoBuffer = NULL;
1406 }
Andreas Huber4d61f602010-06-10 11:17:50 -07001407
1408 if (mCachedSource != NULL && mAudioSource != NULL) {
1409 // We're going to seek the video source first, followed by
1410 // the audio source.
1411 // In order to avoid jumps in the DataSource offset caused by
1412 // the audio codec prefetching data from the old locations
1413 // while the video codec is already reading data from the new
1414 // locations, we'll "pause" the audio source, causing it to
1415 // stop reading input data until a subsequent seek.
1416
1417 if (mAudioPlayer != NULL) {
1418 mAudioPlayer->pause();
1419 }
1420 mAudioSource->pause();
1421 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001422 }
1423
1424 if (!mVideoBuffer) {
1425 MediaSource::ReadOptions options;
1426 if (mSeeking) {
1427 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
1428
Andreas Huber6624c9f2010-07-20 15:04:28 -07001429 options.setSeekTo(
1430 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
Andreas Huber27366fc2009-11-20 09:32:46 -08001431 }
1432 for (;;) {
1433 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberb1f5ee42009-12-14 15:34:11 -08001434 options.clearSeekTo();
Andreas Huber27366fc2009-11-20 09:32:46 -08001435
1436 if (err != OK) {
Andreas Huber52b52cd2010-11-23 11:41:34 -08001437 CHECK(mVideoBuffer == NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -08001438
1439 if (err == INFO_FORMAT_CHANGED) {
1440 LOGV("VideoSource signalled format change.");
1441
Andreas Hubere3c01832010-08-16 08:49:37 -07001442 notifyVideoSize_l();
1443
Andreas Huber7085b6842010-02-03 16:02:02 -08001444 if (mVideoRenderer != NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001445 mVideoRendererIsPreview = false;
Andreas Huber7085b6842010-02-03 16:02:02 -08001446 initRenderer_l();
1447 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001448 continue;
1449 }
1450
Andreas Huber4d450a82010-10-19 09:34:44 -07001451 // So video playback is complete, but we may still have
1452 // a seek request pending that needs to be applied
1453 // to the audio track.
1454 if (mSeeking) {
1455 LOGV("video stream ended while seeking!");
1456 }
1457 finishSeekIfNecessary(-1);
1458
Andreas Huber971305d2010-07-07 13:35:27 -07001459 mFlags |= VIDEO_AT_EOS;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001460 postStreamDoneEvent_l(err);
Andreas Huber27366fc2009-11-20 09:32:46 -08001461 return;
1462 }
1463
Andreas Hubera67d5382009-12-10 15:32:12 -08001464 if (mVideoBuffer->range_length() == 0) {
Andreas Huber6ddcf012009-12-10 15:32:12 -08001465 // Some decoders, notably the PV AVC software decoder
1466 // return spurious empty buffers that we just want to ignore.
1467
Andreas Hubera67d5382009-12-10 15:32:12 -08001468 mVideoBuffer->release();
1469 mVideoBuffer = NULL;
1470 continue;
1471 }
1472
Andreas Huber27366fc2009-11-20 09:32:46 -08001473 break;
1474 }
1475 }
1476
1477 int64_t timeUs;
1478 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1479
Andreas Huber252573c2010-03-26 10:17:17 -07001480 {
1481 Mutex::Autolock autoLock(mMiscStateLock);
1482 mVideoTimeUs = timeUs;
1483 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001484
Andreas Huber614d22c2010-10-29 15:47:52 -07001485 bool wasSeeking = mSeeking;
Andreas Huber4d450a82010-10-19 09:34:44 -07001486 finishSeekIfNecessary(timeUs);
Andreas Huber27366fc2009-11-20 09:32:46 -08001487
Andreas Huber971305d2010-07-07 13:35:27 -07001488 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
1489
Andreas Huber27366fc2009-11-20 09:32:46 -08001490 if (mFlags & FIRST_FRAME) {
1491 mFlags &= ~FIRST_FRAME;
1492
Andreas Huber971305d2010-07-07 13:35:27 -07001493 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
Andreas Huber27366fc2009-11-20 09:32:46 -08001494 }
1495
1496 int64_t realTimeUs, mediaTimeUs;
Andreas Huber971305d2010-07-07 13:35:27 -07001497 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
Andreas Huber27366fc2009-11-20 09:32:46 -08001498 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1499 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1500 }
1501
Andreas Huber971305d2010-07-07 13:35:27 -07001502 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
Andreas Huber27366fc2009-11-20 09:32:46 -08001503
1504 int64_t latenessUs = nowUs - timeUs;
1505
Andreas Huber614d22c2010-10-29 15:47:52 -07001506 if (wasSeeking) {
1507 // Let's display the first frame after seeking right away.
1508 latenessUs = 0;
1509 }
1510
Andreas Huberf88f8442010-08-10 11:18:36 -07001511 if (mRTPSession != NULL) {
1512 // We'll completely ignore timestamps for gtalk videochat
1513 // and we'll play incoming video as fast as we get it.
1514 latenessUs = 0;
1515 }
1516
Andreas Huber24b0a952009-11-23 14:02:00 -08001517 if (latenessUs > 40000) {
1518 // We're more than 40ms late.
Andreas Huber4a9375e2010-02-09 11:54:33 -08001519 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
Andreas Huber27366fc2009-11-20 09:32:46 -08001520
1521 mVideoBuffer->release();
1522 mVideoBuffer = NULL;
1523
1524 postVideoEvent_l();
1525 return;
1526 }
1527
1528 if (latenessUs < -10000) {
1529 // We're more than 10ms early.
1530
1531 postVideoEvent_l(10000);
1532 return;
1533 }
1534
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001535 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
1536 mVideoRendererIsPreview = false;
1537
Andreas Huber7085b6842010-02-03 16:02:02 -08001538 initRenderer_l();
1539 }
1540
1541 if (mVideoRenderer != NULL) {
1542 mVideoRenderer->render(mVideoBuffer);
1543 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001544
Andreas Huber1bb0ffd2010-11-22 13:06:35 -08001545 mVideoBuffer->release();
Andreas Huber27366fc2009-11-20 09:32:46 -08001546 mVideoBuffer = NULL;
1547
1548 postVideoEvent_l();
1549}
1550
1551void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
1552 if (mVideoEventPending) {
1553 return;
1554 }
1555
1556 mVideoEventPending = true;
1557 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1558}
1559
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001560void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001561 if (mStreamDoneEventPending) {
1562 return;
1563 }
1564 mStreamDoneEventPending = true;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001565
1566 mStreamDoneStatus = status;
Andreas Huber27366fc2009-11-20 09:32:46 -08001567 mQueue.postEvent(mStreamDoneEvent);
1568}
1569
Andreas Huberb9e63832010-01-26 16:20:10 -08001570void AwesomePlayer::postBufferingEvent_l() {
Andreas Huberb9e63832010-01-26 16:20:10 -08001571 if (mBufferingEventPending) {
1572 return;
1573 }
1574 mBufferingEventPending = true;
1575 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1576}
1577
Andreas Huber70d10c02010-02-03 11:37:29 -08001578void AwesomePlayer::postCheckAudioStatusEvent_l() {
1579 if (mAudioStatusEventPending) {
1580 return;
1581 }
1582 mAudioStatusEventPending = true;
Andreas Huber2b359ed2010-09-28 11:56:39 -07001583 mQueue.postEvent(mCheckAudioStatusEvent);
Andreas Huber70d10c02010-02-03 11:37:29 -08001584}
1585
1586void AwesomePlayer::onCheckAudioStatus() {
1587 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -08001588 if (!mAudioStatusEventPending) {
1589 // Event was dispatched and while we were blocking on the mutex,
1590 // has already been cancelled.
1591 return;
1592 }
1593
Andreas Huber70d10c02010-02-03 11:37:29 -08001594 mAudioStatusEventPending = false;
1595
1596 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1597 mWatchForAudioSeekComplete = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001598
1599 if (!mSeekNotificationSent) {
1600 notifyListener_l(MEDIA_SEEK_COMPLETE);
1601 mSeekNotificationSent = true;
1602 }
Andreas Huberddb709c2010-04-07 10:24:35 -07001603
1604 mSeeking = false;
Andreas Huber70d10c02010-02-03 11:37:29 -08001605 }
1606
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001607 status_t finalStatus;
1608 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
Andreas Huber70d10c02010-02-03 11:37:29 -08001609 mWatchForAudioEOS = false;
Andreas Huber971305d2010-07-07 13:35:27 -07001610 mFlags |= AUDIO_AT_EOS;
1611 mFlags |= FIRST_FRAME;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001612 postStreamDoneEvent_l(finalStatus);
Andreas Huber70d10c02010-02-03 11:37:29 -08001613 }
Andreas Huber70d10c02010-02-03 11:37:29 -08001614}
1615
Andreas Huber6be780e2010-02-08 14:40:30 -08001616status_t AwesomePlayer::prepare() {
1617 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001618 return prepare_l();
1619}
Andreas Huber6be780e2010-02-08 14:40:30 -08001620
Andreas Huberffdf4782010-02-09 14:05:43 -08001621status_t AwesomePlayer::prepare_l() {
1622 if (mFlags & PREPARED) {
1623 return OK;
1624 }
1625
1626 if (mFlags & PREPARING) {
1627 return UNKNOWN_ERROR;
1628 }
1629
1630 mIsAsyncPrepare = false;
Andreas Huber6be780e2010-02-08 14:40:30 -08001631 status_t err = prepareAsync_l();
1632
1633 if (err != OK) {
1634 return err;
1635 }
1636
Andreas Huberffdf4782010-02-09 14:05:43 -08001637 while (mFlags & PREPARING) {
Andreas Huber6be780e2010-02-08 14:40:30 -08001638 mPreparedCondition.wait(mLock);
1639 }
1640
Andreas Huberffdf4782010-02-09 14:05:43 -08001641 return mPrepareResult;
Andreas Huber6be780e2010-02-08 14:40:30 -08001642}
1643
1644status_t AwesomePlayer::prepareAsync() {
1645 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001646
1647 if (mFlags & PREPARING) {
1648 return UNKNOWN_ERROR; // async prepare already pending
1649 }
1650
1651 mIsAsyncPrepare = true;
Andreas Huber6be780e2010-02-08 14:40:30 -08001652 return prepareAsync_l();
1653}
1654
1655status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001656 if (mFlags & PREPARING) {
1657 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huber6be780e2010-02-08 14:40:30 -08001658 }
1659
Andreas Huber406a18b2010-02-18 16:45:13 -08001660 if (!mQueueStarted) {
1661 mQueue.start();
1662 mQueueStarted = true;
1663 }
1664
Andreas Huberffdf4782010-02-09 14:05:43 -08001665 mFlags |= PREPARING;
Andreas Huber6be780e2010-02-08 14:40:30 -08001666 mAsyncPrepareEvent = new AwesomeEvent(
1667 this, &AwesomePlayer::onPrepareAsyncEvent);
1668
1669 mQueue.postEvent(mAsyncPrepareEvent);
1670
1671 return OK;
1672}
1673
Andreas Huberffdf4782010-02-09 14:05:43 -08001674status_t AwesomePlayer::finishSetDataSource_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001675 sp<DataSource> dataSource;
1676
1677 if (!strncasecmp("http://", mUri.string(), 7)) {
Andreas Huber4d61f602010-06-10 11:17:50 -07001678 mConnectingDataSource = new NuHTTPDataSource;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001679
1680 mLock.unlock();
Andreas Huber3a53dc52010-06-11 09:57:46 -07001681 status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001682 mLock.lock();
1683
1684 if (err != OK) {
1685 mConnectingDataSource.clear();
1686
1687 LOGI("mConnectingDataSource->connect() returned %d", err);
1688 return err;
1689 }
1690
Andreas Huber4d61f602010-06-10 11:17:50 -07001691#if 0
1692 mCachedSource = new NuCachedSource2(
1693 new ThrottledSource(
1694 mConnectingDataSource, 50 * 1024 /* bytes/sec */));
1695#else
1696 mCachedSource = new NuCachedSource2(mConnectingDataSource);
1697#endif
Andreas Huberedbb4d82010-03-12 08:59:22 -08001698 mConnectingDataSource.clear();
Andreas Huber4d61f602010-06-10 11:17:50 -07001699
1700 dataSource = mCachedSource;
Andreas Huber202348e2010-06-07 14:35:29 -07001701 } else if (!strncasecmp(mUri.string(), "httplive://", 11)) {
1702 String8 uri("http://");
1703 uri.append(mUri.string() + 11);
1704
Andreas Huberb5590842010-12-03 16:12:25 -08001705 if (mLooper == NULL) {
1706 mLooper = new ALooper;
1707 mLooper->setName("httplive");
1708 mLooper->start();
1709 }
Andreas Huber202348e2010-06-07 14:35:29 -07001710
Andreas Huberb5590842010-12-03 16:12:25 -08001711 mLiveSession = new LiveSession;
1712 mLooper->registerHandler(mLiveSession);
1713
1714 mLiveSession->connect(uri.string());
1715 dataSource = mLiveSession->getDataSource();
Andreas Huber202348e2010-06-07 14:35:29 -07001716
1717 sp<MediaExtractor> extractor =
1718 MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
Andreas Huber4d61f602010-06-10 11:17:50 -07001719
Andreas Huber54d09722010-10-12 11:34:37 -07001720 static_cast<MPEG2TSExtractor *>(extractor.get())
Andreas Huberb5590842010-12-03 16:12:25 -08001721 ->setLiveSession(mLiveSession);
Andreas Huber54d09722010-10-12 11:34:37 -07001722
Andreas Huber4d61f602010-06-10 11:17:50 -07001723 return setDataSource_l(extractor);
Mike Dodd8741dfa2010-08-12 16:04:35 -07001724 } else if (!strncmp("rtsp://gtalk/", mUri.string(), 13)) {
Andreas Huber57648e42010-08-04 10:14:30 -07001725 if (mLooper == NULL) {
1726 mLooper = new ALooper;
Andreas Huberc4e0b702010-08-27 15:21:07 -07001727 mLooper->setName("gtalk rtp");
Andreas Huber3eaa3002010-08-05 09:22:25 -07001728 mLooper->start(
1729 false /* runOnCallingThread */,
1730 false /* canCallJava */,
1731 PRIORITY_HIGHEST);
Andreas Huber57648e42010-08-04 10:14:30 -07001732 }
1733
Mike Dodd8741dfa2010-08-12 16:04:35 -07001734 const char *startOfCodecString = &mUri.string()[13];
1735 const char *startOfSlash1 = strchr(startOfCodecString, '/');
1736 if (startOfSlash1 == NULL) {
1737 return BAD_VALUE;
1738 }
1739 const char *startOfWidthString = &startOfSlash1[1];
1740 const char *startOfSlash2 = strchr(startOfWidthString, '/');
1741 if (startOfSlash2 == NULL) {
1742 return BAD_VALUE;
1743 }
1744 const char *startOfHeightString = &startOfSlash2[1];
1745
1746 String8 codecString(startOfCodecString, startOfSlash1 - startOfCodecString);
1747 String8 widthString(startOfWidthString, startOfSlash2 - startOfWidthString);
1748 String8 heightString(startOfHeightString);
1749
Andreas Huber57648e42010-08-04 10:14:30 -07001750#if 0
1751 mRTPPusher = new UDPPusher("/data/misc/rtpout.bin", 5434);
1752 mLooper->registerHandler(mRTPPusher);
1753
1754 mRTCPPusher = new UDPPusher("/data/misc/rtcpout.bin", 5435);
1755 mLooper->registerHandler(mRTCPPusher);
1756#endif
1757
1758 mRTPSession = new ARTPSession;
1759 mLooper->registerHandler(mRTPSession);
1760
1761#if 0
Andreas Huber57648e42010-08-04 10:14:30 -07001762 // My AMR SDP
1763 static const char *raw =
1764 "v=0\r\n"
1765 "o=- 64 233572944 IN IP4 127.0.0.0\r\n"
1766 "s=QuickTime\r\n"
1767 "t=0 0\r\n"
1768 "a=range:npt=0-315\r\n"
1769 "a=isma-compliance:2,2.0,2\r\n"
1770 "m=audio 5434 RTP/AVP 97\r\n"
1771 "c=IN IP4 127.0.0.1\r\n"
1772 "b=AS:30\r\n"
1773 "a=rtpmap:97 AMR/8000/1\r\n"
1774 "a=fmtp:97 octet-align\r\n";
1775#elif 1
Mike Dodd8741dfa2010-08-12 16:04:35 -07001776 String8 sdp;
1777 sdp.appendFormat(
Andreas Huber57648e42010-08-04 10:14:30 -07001778 "v=0\r\n"
1779 "o=- 64 233572944 IN IP4 127.0.0.0\r\n"
1780 "s=QuickTime\r\n"
1781 "t=0 0\r\n"
1782 "a=range:npt=0-315\r\n"
1783 "a=isma-compliance:2,2.0,2\r\n"
1784 "m=video 5434 RTP/AVP 97\r\n"
1785 "c=IN IP4 127.0.0.1\r\n"
1786 "b=AS:30\r\n"
Mike Dodd8741dfa2010-08-12 16:04:35 -07001787 "a=rtpmap:97 %s/90000\r\n"
1788 "a=cliprect:0,0,%s,%s\r\n"
1789 "a=framesize:97 %s-%s\r\n",
1790
1791 codecString.string(),
1792 heightString.string(), widthString.string(),
1793 widthString.string(), heightString.string()
1794 );
1795 const char *raw = sdp.string();
1796
Andreas Huber57648e42010-08-04 10:14:30 -07001797#endif
1798
1799 sp<ASessionDescription> desc = new ASessionDescription;
1800 CHECK(desc->setTo(raw, strlen(raw)));
1801
1802 CHECK_EQ(mRTPSession->setup(desc), (status_t)OK);
1803
1804 if (mRTPPusher != NULL) {
1805 mRTPPusher->start();
1806 }
1807
1808 if (mRTCPPusher != NULL) {
1809 mRTCPPusher->start();
1810 }
1811
1812 CHECK_EQ(mRTPSession->countTracks(), 1u);
1813 sp<MediaSource> source = mRTPSession->trackAt(0);
1814
1815#if 0
1816 bool eos;
1817 while (((APacketSource *)source.get())
1818 ->getQueuedDuration(&eos) < 5000000ll && !eos) {
1819 usleep(100000ll);
1820 }
1821#endif
1822
1823 const char *mime;
1824 CHECK(source->getFormat()->findCString(kKeyMIMEType, &mime));
1825
1826 if (!strncasecmp("video/", mime, 6)) {
1827 setVideoSource(source);
1828 } else {
1829 CHECK(!strncasecmp("audio/", mime, 6));
1830 setAudioSource(source);
1831 }
1832
1833 mExtractorFlags = MediaExtractor::CAN_PAUSE;
1834
1835 return OK;
Andreas Huber7a747b82010-06-07 15:19:40 -07001836 } else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
1837 if (mLooper == NULL) {
1838 mLooper = new ALooper;
Andreas Huberc4e0b702010-08-27 15:21:07 -07001839 mLooper->setName("rtsp");
Andreas Huber7a747b82010-06-07 15:19:40 -07001840 mLooper->start();
1841 }
1842 mRTSPController = new ARTSPController(mLooper);
1843 status_t err = mRTSPController->connect(mUri.string());
Andreas Huber202348e2010-06-07 14:35:29 -07001844
Andreas Huber7a747b82010-06-07 15:19:40 -07001845 LOGI("ARTSPController::connect returned %d", err);
1846
1847 if (err != OK) {
1848 mRTSPController.clear();
1849 return err;
1850 }
1851
1852 sp<MediaExtractor> extractor = mRTSPController.get();
Andreas Huber202348e2010-06-07 14:35:29 -07001853 return setDataSource_l(extractor);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001854 } else {
1855 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1856 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001857
1858 if (dataSource == NULL) {
1859 return UNKNOWN_ERROR;
1860 }
1861
1862 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1863
1864 if (extractor == NULL) {
1865 return UNKNOWN_ERROR;
1866 }
1867
Gloria Wangd5770912010-06-22 13:55:38 -07001868 dataSource->getDrmInfo(&mDecryptHandle, &mDrmManagerClient);
Gloria Wangc2c22e72010-11-01 15:53:16 -07001869 if (mDecryptHandle != NULL) {
1870 if (RightsStatus::RIGHTS_VALID == mDecryptHandle->status) {
1871 if (DecryptApiType::WV_BASED == mDecryptHandle->decryptApiType) {
1872 LOGD("Setting mCachedSource to NULL for WVM\n");
1873 mCachedSource.clear();
1874 }
1875 } else {
1876 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_NO_LICENSE);
1877 }
Gloria Wangd5770912010-06-22 13:55:38 -07001878 }
1879
Andreas Huberffdf4782010-02-09 14:05:43 -08001880 return setDataSource_l(extractor);
1881}
1882
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001883void AwesomePlayer::abortPrepare(status_t err) {
1884 CHECK(err != OK);
1885
1886 if (mIsAsyncPrepare) {
1887 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1888 }
1889
1890 mPrepareResult = err;
Andreas Hubereaf2c5a2010-10-19 12:18:51 -07001891 mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001892 mAsyncPrepareEvent = NULL;
1893 mPreparedCondition.broadcast();
1894}
1895
Andreas Huberf71daba2010-03-24 09:24:40 -07001896// static
1897bool AwesomePlayer::ContinuePreparation(void *cookie) {
1898 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
1899
1900 return (me->mFlags & PREPARE_CANCELLED) == 0;
1901}
1902
Andreas Huber6be780e2010-02-08 14:40:30 -08001903void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001904 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001905
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001906 if (mFlags & PREPARE_CANCELLED) {
1907 LOGI("prepare was cancelled before doing anything");
1908 abortPrepare(UNKNOWN_ERROR);
1909 return;
1910 }
1911
1912 if (mUri.size() > 0) {
1913 status_t err = finishSetDataSource_l();
1914
1915 if (err != OK) {
1916 abortPrepare(err);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001917 return;
1918 }
Andreas Huber6be780e2010-02-08 14:40:30 -08001919 }
1920
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001921 if (mVideoTrack != NULL && mVideoSource == NULL) {
1922 status_t err = initVideoDecoder();
Andreas Huber6be780e2010-02-08 14:40:30 -08001923
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001924 if (err != OK) {
1925 abortPrepare(err);
1926 return;
1927 }
1928 }
1929
1930 if (mAudioTrack != NULL && mAudioSource == NULL) {
1931 status_t err = initAudioDecoder();
1932
1933 if (err != OK) {
1934 abortPrepare(err);
1935 return;
1936 }
1937 }
1938
Andreas Hubereaf2c5a2010-10-19 12:18:51 -07001939 mFlags |= PREPARING_CONNECTED;
1940
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001941 if (mCachedSource != NULL || mRTSPController != NULL) {
1942 postBufferingEvent_l();
1943 } else {
1944 finishAsyncPrepare_l();
1945 }
1946}
1947
1948void AwesomePlayer::finishAsyncPrepare_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001949 if (mIsAsyncPrepare) {
Andreas Hubere3c01832010-08-16 08:49:37 -07001950 if (mVideoSource == NULL) {
Andreas Huberffdf4782010-02-09 14:05:43 -08001951 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1952 } else {
Andreas Hubere3c01832010-08-16 08:49:37 -07001953 notifyVideoSize_l();
Andreas Huberffdf4782010-02-09 14:05:43 -08001954 }
1955
1956 notifyListener_l(MEDIA_PREPARED);
Andreas Huber6be780e2010-02-08 14:40:30 -08001957 }
1958
Andreas Huberffdf4782010-02-09 14:05:43 -08001959 mPrepareResult = OK;
Andreas Hubereaf2c5a2010-10-19 12:18:51 -07001960 mFlags &= ~(PREPARING|PREPARE_CANCELLED|PREPARING_CONNECTED);
Andreas Huberffdf4782010-02-09 14:05:43 -08001961 mFlags |= PREPARED;
Andreas Huber6be780e2010-02-08 14:40:30 -08001962 mAsyncPrepareEvent = NULL;
Andreas Huberffdf4782010-02-09 14:05:43 -08001963 mPreparedCondition.broadcast();
Andreas Huber6be780e2010-02-08 14:40:30 -08001964}
1965
Andreas Huber62f7ffe2010-05-06 10:18:05 -07001966uint32_t AwesomePlayer::flags() const {
1967 return mExtractorFlags;
1968}
1969
Andreas Huber2b359ed2010-09-28 11:56:39 -07001970void AwesomePlayer::postAudioEOS() {
1971 postCheckAudioStatusEvent_l();
1972}
1973
1974void AwesomePlayer::postAudioSeekComplete() {
1975 postCheckAudioStatusEvent_l();
1976}
1977
Andreas Huber27366fc2009-11-20 09:32:46 -08001978} // namespace android