blob: c13726ba6b8cd1ddd271cc3ea75ee0f7b16d4d4d [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 Huber7a747b82010-06-07 15:19:40 -070025#include "include/LiveSource.h"
Andreas Huber1314e732009-12-14 14:18:22 -080026#include "include/SoftwareRenderer.h"
Andreas Huber4d61f602010-06-10 11:17:50 -070027#include "include/NuCachedSource2.h"
28#include "include/ThrottledSource.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 Huber27366fc2009-11-20 09:32:46 -080036#include <media/stagefright/AudioPlayer.h>
37#include <media/stagefright/DataSource.h>
38#include <media/stagefright/FileSource.h>
39#include <media/stagefright/MediaBuffer.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080040#include <media/stagefright/MediaDefs.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080041#include <media/stagefright/MediaExtractor.h>
42#include <media/stagefright/MediaDebug.h>
43#include <media/stagefright/MediaSource.h>
44#include <media/stagefright/MetaData.h>
45#include <media/stagefright/OMXCodec.h>
Andreas Huberc79827a2010-01-05 10:54:55 -080046
Mathias Agopian000479f2010-02-09 17:46:37 -080047#include <surfaceflinger/ISurface.h>
48
Andreas Huber7a747b82010-06-07 15:19:40 -070049#include <media/stagefright/foundation/ALooper.h>
Andreas Huber202348e2010-06-07 14:35:29 -070050
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
55
Andreas Huber27366fc2009-11-20 09:32:46 -080056struct AwesomeEvent : public TimedEventQueue::Event {
Andreas Huber6be780e2010-02-08 14:40:30 -080057 AwesomeEvent(
58 AwesomePlayer *player,
59 void (AwesomePlayer::*method)())
Andreas Huber27366fc2009-11-20 09:32:46 -080060 : mPlayer(player),
Andreas Huber6be780e2010-02-08 14:40:30 -080061 mMethod(method) {
Andreas Huber27366fc2009-11-20 09:32:46 -080062 }
63
64protected:
65 virtual ~AwesomeEvent() {}
66
67 virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
Andreas Huber6be780e2010-02-08 14:40:30 -080068 (mPlayer->*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080069 }
70
71private:
72 AwesomePlayer *mPlayer;
Andreas Huber6be780e2010-02-08 14:40:30 -080073 void (AwesomePlayer::*mMethod)();
Andreas Huber27366fc2009-11-20 09:32:46 -080074
75 AwesomeEvent(const AwesomeEvent &);
76 AwesomeEvent &operator=(const AwesomeEvent &);
77};
78
Andreas Huber1314e732009-12-14 14:18:22 -080079struct AwesomeRemoteRenderer : public AwesomeRenderer {
80 AwesomeRemoteRenderer(const sp<IOMXRenderer> &target)
81 : mTarget(target) {
82 }
83
84 virtual void render(MediaBuffer *buffer) {
85 void *id;
86 if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) {
87 mTarget->render((IOMX::buffer_id)id);
88 }
89 }
90
91private:
92 sp<IOMXRenderer> mTarget;
93
94 AwesomeRemoteRenderer(const AwesomeRemoteRenderer &);
95 AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &);
96};
97
98struct AwesomeLocalRenderer : public AwesomeRenderer {
99 AwesomeLocalRenderer(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800100 bool previewOnly,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800101 const char *componentName,
Andreas Huber1314e732009-12-14 14:18:22 -0800102 OMX_COLOR_FORMATTYPE colorFormat,
103 const sp<ISurface> &surface,
104 size_t displayWidth, size_t displayHeight,
105 size_t decodedWidth, size_t decodedHeight)
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800106 : mTarget(NULL),
107 mLibHandle(NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800108 init(previewOnly, componentName,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800109 colorFormat, surface, displayWidth,
110 displayHeight, decodedWidth, decodedHeight);
Andreas Huber1314e732009-12-14 14:18:22 -0800111 }
112
113 virtual void render(MediaBuffer *buffer) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800114 render((const uint8_t *)buffer->data() + buffer->range_offset(),
115 buffer->range_length());
116 }
117
118 void render(const void *data, size_t size) {
119 mTarget->render(data, size, NULL);
Andreas Huber1314e732009-12-14 14:18:22 -0800120 }
121
122protected:
123 virtual ~AwesomeLocalRenderer() {
124 delete mTarget;
125 mTarget = NULL;
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800126
127 if (mLibHandle) {
128 dlclose(mLibHandle);
129 mLibHandle = NULL;
130 }
Andreas Huber1314e732009-12-14 14:18:22 -0800131 }
132
133private:
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800134 VideoRenderer *mTarget;
135 void *mLibHandle;
136
137 void init(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800138 bool previewOnly,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800139 const char *componentName,
140 OMX_COLOR_FORMATTYPE colorFormat,
141 const sp<ISurface> &surface,
142 size_t displayWidth, size_t displayHeight,
143 size_t decodedWidth, size_t decodedHeight);
Andreas Huber1314e732009-12-14 14:18:22 -0800144
145 AwesomeLocalRenderer(const AwesomeLocalRenderer &);
146 AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
147};
148
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800149void AwesomeLocalRenderer::init(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800150 bool previewOnly,
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800151 const char *componentName,
152 OMX_COLOR_FORMATTYPE colorFormat,
153 const sp<ISurface> &surface,
154 size_t displayWidth, size_t displayHeight,
155 size_t decodedWidth, size_t decodedHeight) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800156 if (!previewOnly) {
157 // We will stick to the vanilla software-color-converting renderer
158 // for "previewOnly" mode, to avoid unneccessarily switching overlays
159 // more often than necessary.
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800160
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800161 mLibHandle = dlopen("libstagefrighthw.so", RTLD_NOW);
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800162
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800163 if (mLibHandle) {
164 typedef VideoRenderer *(*CreateRendererFunc)(
165 const sp<ISurface> &surface,
166 const char *componentName,
167 OMX_COLOR_FORMATTYPE colorFormat,
168 size_t displayWidth, size_t displayHeight,
169 size_t decodedWidth, size_t decodedHeight);
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800170
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800171 CreateRendererFunc func =
172 (CreateRendererFunc)dlsym(
173 mLibHandle,
174 "_Z14createRendererRKN7android2spINS_8ISurfaceEEEPKc20"
175 "OMX_COLOR_FORMATTYPEjjjj");
176
177 if (func) {
178 mTarget =
179 (*func)(surface, componentName, colorFormat,
180 displayWidth, displayHeight,
181 decodedWidth, decodedHeight);
182 }
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800183 }
184 }
185
186 if (mTarget == NULL) {
187 mTarget = new SoftwareRenderer(
188 colorFormat, surface, displayWidth, displayHeight,
189 decodedWidth, decodedHeight);
190 }
191}
192
Andreas Huber27366fc2009-11-20 09:32:46 -0800193AwesomePlayer::AwesomePlayer()
Andreas Huber406a18b2010-02-18 16:45:13 -0800194 : mQueueStarted(false),
195 mTimeSource(NULL),
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800196 mVideoRendererIsPreview(false),
Andreas Huber27366fc2009-11-20 09:32:46 -0800197 mAudioPlayer(NULL),
Andreas Huberffdf4782010-02-09 14:05:43 -0800198 mFlags(0),
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700199 mExtractorFlags(0),
Andreas Huber27366fc2009-11-20 09:32:46 -0800200 mLastVideoBuffer(NULL),
Andreas Huberba7ec912010-02-12 10:42:02 -0800201 mVideoBuffer(NULL),
202 mSuspensionState(NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800203 CHECK_EQ(mClient.connect(), OK);
204
205 DataSource::RegisterDefaultSniffers();
206
Andreas Huber6be780e2010-02-08 14:40:30 -0800207 mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
Andreas Huber27366fc2009-11-20 09:32:46 -0800208 mVideoEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800209 mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
Andreas Huber27366fc2009-11-20 09:32:46 -0800210 mStreamDoneEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800211 mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
Andreas Huberb9e63832010-01-26 16:20:10 -0800212 mBufferingEventPending = false;
Andreas Huber6be780e2010-02-08 14:40:30 -0800213
214 mCheckAudioStatusEvent = new AwesomeEvent(
215 this, &AwesomePlayer::onCheckAudioStatus);
216
Andreas Huber70d10c02010-02-03 11:37:29 -0800217 mAudioStatusEventPending = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800218
Andreas Huber27366fc2009-11-20 09:32:46 -0800219 reset();
220}
221
222AwesomePlayer::~AwesomePlayer() {
Andreas Huber406a18b2010-02-18 16:45:13 -0800223 if (mQueueStarted) {
224 mQueue.stop();
225 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800226
227 reset();
228
229 mClient.disconnect();
230}
231
Andreas Huberb9e63832010-01-26 16:20:10 -0800232void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800233 mQueue.cancelEvent(mVideoEvent->eventID());
234 mVideoEventPending = false;
235 mQueue.cancelEvent(mStreamDoneEvent->eventID());
236 mStreamDoneEventPending = false;
Andreas Huber70d10c02010-02-03 11:37:29 -0800237 mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
238 mAudioStatusEventPending = false;
Andreas Huberb9e63832010-01-26 16:20:10 -0800239
240 if (!keepBufferingGoing) {
241 mQueue.cancelEvent(mBufferingEvent->eventID());
242 mBufferingEventPending = false;
243 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800244}
245
Andreas Hubera3f43842010-01-21 10:28:45 -0800246void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800247 Mutex::Autolock autoLock(mLock);
248 mListener = listener;
249}
250
Andreas Huber433c9ac2010-01-27 16:49:05 -0800251status_t AwesomePlayer::setDataSource(
252 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800253 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800254 return setDataSource_l(uri, headers);
255}
Andreas Huber27366fc2009-11-20 09:32:46 -0800256
Andreas Huberba7ec912010-02-12 10:42:02 -0800257status_t AwesomePlayer::setDataSource_l(
258 const char *uri, const KeyedVector<String8, String8> *headers) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800259 reset_l();
260
Andreas Huberffdf4782010-02-09 14:05:43 -0800261 mUri = uri;
Andreas Huberb9e63832010-01-26 16:20:10 -0800262
Andreas Huberffdf4782010-02-09 14:05:43 -0800263 if (headers) {
264 mUriHeaders = *headers;
Andreas Huberb9e63832010-01-26 16:20:10 -0800265 }
266
Andreas Huberffdf4782010-02-09 14:05:43 -0800267 // The actual work will be done during preparation in the call to
268 // ::finishSetDataSource_l to avoid blocking the calling thread in
269 // setDataSource for any significant time.
Andreas Huber27366fc2009-11-20 09:32:46 -0800270
Andreas Huberffdf4782010-02-09 14:05:43 -0800271 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800272}
273
274status_t AwesomePlayer::setDataSource(
275 int fd, int64_t offset, int64_t length) {
Andreas Huber202348e2010-06-07 14:35:29 -0700276#if 0
Andreas Huber4dcc6a12010-09-01 12:22:36 -0700277 // return setDataSource("httplive://qthttp.apple.com.edgesuite.net/1009qpeijrfn/sl.m3u8");
278 return setDataSource("httplive://qthttp.apple.com.edgesuite.net/1009qpeijrfn/0440.m3u8");
279 // return setDataSource("httplive://qthttp.apple.com.edgesuite.net/1009qpeijrfn/0640.m3u8");
280 // return setDataSource("httplive://qthttp.apple.com.edgesuite.net/1009qpeijrfn/1240_vod.m3u8");
Andreas Huber202348e2010-06-07 14:35:29 -0700281 // return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/nasatv/nasatv_96.m3u8");
282 // return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/nasatv/nasatv_1500.m3u8");
Andreas Huber4dcc6a12010-09-01 12:22:36 -0700283 // return setDataSource("httplive://iphone.video.hsn.com/iPhone_high.m3u8");
Andreas Huber202348e2010-06-07 14:35:29 -0700284 // return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/iphonewebcast/webcast090209_all/webcast090209_all.m3u8");
285 // return setDataSource("httplive://qthttp.akamai.com.edgesuite.net/iphone_demo/Video_Content/usat/tt_062209_iphone/hi/prog_index.m3u8");
286 // return setDataSource("httplive://qthttp.akamai.com.edgesuite.net/iphone_demo/Video_Content/usat/tt_googmaps/hi/prog_index.m3u8");
287 // return setDataSource("httplive://qthttp.akamai.com.edgesuite.net/iphone_demo/Video_Content/mtv/ni_spo_25a_rt74137_clip_syn/hi/prog_index.m3u8");
288#endif
289
Andreas Huber27366fc2009-11-20 09:32:46 -0800290 Mutex::Autolock autoLock(mLock);
291
292 reset_l();
293
Andreas Huberba7ec912010-02-12 10:42:02 -0800294 sp<DataSource> dataSource = new FileSource(fd, offset, length);
Andreas Huber27366fc2009-11-20 09:32:46 -0800295
Andreas Huberba7ec912010-02-12 10:42:02 -0800296 status_t err = dataSource->initCheck();
Andreas Huber27366fc2009-11-20 09:32:46 -0800297
298 if (err != OK) {
299 return err;
300 }
301
Andreas Huberba7ec912010-02-12 10:42:02 -0800302 mFileSource = dataSource;
303
304 return setDataSource_l(dataSource);
305}
306
307status_t AwesomePlayer::setDataSource_l(
308 const sp<DataSource> &dataSource) {
309 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
Andreas Huber27366fc2009-11-20 09:32:46 -0800310
311 if (extractor == NULL) {
312 return UNKNOWN_ERROR;
313 }
314
315 return setDataSource_l(extractor);
316}
317
318status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800319 bool haveAudio = false;
320 bool haveVideo = false;
321 for (size_t i = 0; i < extractor->countTracks(); ++i) {
322 sp<MetaData> meta = extractor->getTrackMetaData(i);
323
324 const char *mime;
325 CHECK(meta->findCString(kKeyMIMEType, &mime));
326
327 if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800328 setVideoSource(extractor->getTrack(i));
329 haveVideo = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800330 } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800331 setAudioSource(extractor->getTrack(i));
332 haveAudio = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800333 }
334
335 if (haveAudio && haveVideo) {
336 break;
337 }
338 }
339
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700340 if (!haveAudio && !haveVideo) {
341 return UNKNOWN_ERROR;
342 }
343
344 mExtractorFlags = extractor->flags();
345
346 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800347}
348
349void AwesomePlayer::reset() {
350 Mutex::Autolock autoLock(mLock);
351 reset_l();
352}
353
354void AwesomePlayer::reset_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -0800355 if (mFlags & PREPARING) {
356 mFlags |= PREPARE_CANCELLED;
357 if (mConnectingDataSource != NULL) {
358 LOGI("interrupting the connection process");
359 mConnectingDataSource->disconnect();
360 }
361 }
362
Andreas Huberffdf4782010-02-09 14:05:43 -0800363 while (mFlags & PREPARING) {
364 mPreparedCondition.wait(mLock);
365 }
366
Andreas Huber27366fc2009-11-20 09:32:46 -0800367 cancelPlayerEvents();
368
Andreas Huber4d61f602010-06-10 11:17:50 -0700369 mCachedSource.clear();
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800370 mAudioTrack.clear();
371 mVideoTrack.clear();
372
Andreas Huberba7ec912010-02-12 10:42:02 -0800373 // Shutdown audio first, so that the respone to the reset request
374 // appears to happen instantaneously as far as the user is concerned
375 // If we did this later, audio would continue playing while we
376 // shutdown the video-related resources and the player appear to
377 // not be as responsive to a reset request.
Andreas Huberedbb4d82010-03-12 08:59:22 -0800378 if (mAudioPlayer == NULL && mAudioSource != NULL) {
379 // If we had an audio player, it would have effectively
380 // taken possession of the audio source and stopped it when
381 // _it_ is stopped. Otherwise this is still our responsibility.
382 mAudioSource->stop();
383 }
Andreas Huberba7ec912010-02-12 10:42:02 -0800384 mAudioSource.clear();
385
Andreas Huberba7ec912010-02-12 10:42:02 -0800386 mTimeSource = NULL;
387
388 delete mAudioPlayer;
389 mAudioPlayer = NULL;
390
Andreas Huber3522b5a52010-01-22 14:36:53 -0800391 mVideoRenderer.clear();
392
Andreas Huber27366fc2009-11-20 09:32:46 -0800393 if (mLastVideoBuffer) {
394 mLastVideoBuffer->release();
395 mLastVideoBuffer = NULL;
396 }
397
398 if (mVideoBuffer) {
399 mVideoBuffer->release();
400 mVideoBuffer = NULL;
401 }
402
Andreas Hubere0dd7d32010-08-24 14:33:58 -0700403 if (mRTSPController != NULL) {
404 mRTSPController->disconnect();
405 mRTSPController.clear();
406 }
407
Andreas Huber57648e42010-08-04 10:14:30 -0700408 mRTPPusher.clear();
409 mRTCPPusher.clear();
410 mRTPSession.clear();
Andreas Huber7a747b82010-06-07 15:19:40 -0700411
Andreas Huber27366fc2009-11-20 09:32:46 -0800412 if (mVideoSource != NULL) {
413 mVideoSource->stop();
Andreas Huber98b48de2010-01-29 10:10:22 -0800414
415 // The following hack is necessary to ensure that the OMX
416 // component is completely released by the time we may try
417 // to instantiate it again.
418 wp<MediaSource> tmp = mVideoSource;
Andreas Huber27366fc2009-11-20 09:32:46 -0800419 mVideoSource.clear();
Andreas Huber98b48de2010-01-29 10:10:22 -0800420 while (tmp.promote() != NULL) {
421 usleep(1000);
422 }
423 IPCThreadState::self()->flushCommands();
Andreas Huber27366fc2009-11-20 09:32:46 -0800424 }
425
Andreas Huber27366fc2009-11-20 09:32:46 -0800426 mDurationUs = -1;
427 mFlags = 0;
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700428 mExtractorFlags = 0;
Andreas Huber27366fc2009-11-20 09:32:46 -0800429 mVideoWidth = mVideoHeight = -1;
430 mTimeSourceDeltaUs = 0;
431 mVideoTimeUs = 0;
432
433 mSeeking = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700434 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800435 mSeekTimeUs = 0;
Andreas Huberb9e63832010-01-26 16:20:10 -0800436
Andreas Huberffdf4782010-02-09 14:05:43 -0800437 mUri.setTo("");
438 mUriHeaders.clear();
Andreas Huberba7ec912010-02-12 10:42:02 -0800439
440 mFileSource.clear();
441
442 delete mSuspensionState;
443 mSuspensionState = NULL;
Andreas Huber27366fc2009-11-20 09:32:46 -0800444}
445
Andreas Huber6be780e2010-02-08 14:40:30 -0800446void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
Andreas Hubera3f43842010-01-21 10:28:45 -0800447 if (mListener != NULL) {
448 sp<MediaPlayerBase> listener = mListener.promote();
449
450 if (listener != NULL) {
Andreas Huber6be780e2010-02-08 14:40:30 -0800451 listener->sendEvent(msg, ext1, ext2);
Andreas Hubera3f43842010-01-21 10:28:45 -0800452 }
453 }
454}
455
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700456// Returns true iff cached duration is available/applicable.
457bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
458 off_t totalSize;
459
460 if (mRTSPController != NULL) {
461 *durationUs = mRTSPController->getQueueDurationUs(eos);
462 return true;
463 } else if (mCachedSource != NULL && mDurationUs >= 0
464 && mCachedSource->getSize(&totalSize) == OK) {
465 int64_t bitrate = totalSize * 8000000ll / mDurationUs; // in bits/sec
466
467 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(eos);
468 *durationUs = cachedDataRemaining * 8000000ll / bitrate;
469 return true;
470 }
471
472 return false;
473}
474
Andreas Huberb9e63832010-01-26 16:20:10 -0800475void AwesomePlayer::onBufferingUpdate() {
476 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800477 if (!mBufferingEventPending) {
478 return;
479 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800480 mBufferingEventPending = false;
481
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700482 if (mCachedSource != NULL) {
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700483 bool eos;
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700484 size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&eos);
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700485
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700486 if (eos) {
487 notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
488 } else {
489 off_t size;
490 if (mDurationUs >= 0 && mCachedSource->getSize(&size) == OK) {
491 int64_t bitrate = size * 8000000ll / mDurationUs; // in bits/sec
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700492
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700493 size_t cachedSize = mCachedSource->cachedSize();
494 int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
495
496 int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
497 if (percentage > 100) {
498 percentage = 100;
499 }
500
501 notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
502 } else {
503 // We don't know the bitrate of the stream, use absolute size
504 // limits to maintain the cache.
505
506 const size_t kLowWaterMarkBytes = 400000;
507 const size_t kHighWaterMarkBytes = 1000000;
508
509 if ((mFlags & PLAYING) && !eos
510 && (cachedDataRemaining < kLowWaterMarkBytes)) {
511 LOGI("cache is running low (< %d) , pausing.",
512 kLowWaterMarkBytes);
513 mFlags |= CACHE_UNDERRUN;
514 pause_l();
515 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
516 } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
517 if (mFlags & CACHE_UNDERRUN) {
518 LOGI("cache has filled up (> %d), resuming.",
519 kHighWaterMarkBytes);
520 mFlags &= ~CACHE_UNDERRUN;
521 play_l();
522 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
523 } else if (mFlags & PREPARING) {
524 LOGV("cache has filled up (> %d), prepare is done",
525 kHighWaterMarkBytes);
526 finishAsyncPrepare_l();
527 }
528 }
529 }
530 }
531 }
532
533 int64_t cachedDurationUs;
534 bool eos;
535 if (getCachedDuration_l(&cachedDurationUs, &eos)) {
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700536 if ((mFlags & PLAYING) && !eos
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700537 && (cachedDurationUs < kLowWaterMarkUs)) {
538 LOGI("cache is running low (%.2f secs) , pausing.",
539 cachedDurationUs / 1E6);
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700540 mFlags |= CACHE_UNDERRUN;
541 pause_l();
542 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
Andreas Huber87ab9cd2010-09-03 13:20:33 -0700543 } else if (eos || cachedDurationUs > kHighWaterMarkUs) {
544 if (mFlags & CACHE_UNDERRUN) {
545 LOGI("cache has filled up (%.2f secs), resuming.",
546 cachedDurationUs / 1E6);
547 mFlags &= ~CACHE_UNDERRUN;
548 play_l();
549 notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
550 } else if (mFlags & PREPARING) {
551 LOGV("cache has filled up (%.2f secs), prepare is done",
552 cachedDurationUs / 1E6);
553 finishAsyncPrepare_l();
Andreas Huberc23296e2010-08-25 12:31:48 -0700554 }
Andreas Huberc23296e2010-08-25 12:31:48 -0700555 }
Andreas Huberb9e63832010-01-26 16:20:10 -0800556 }
Andreas Huber4d61f602010-06-10 11:17:50 -0700557
Andreas Huber4d61f602010-06-10 11:17:50 -0700558 postBufferingEvent_l();
Andreas Huberb9e63832010-01-26 16:20:10 -0800559}
560
Andreas Huber27366fc2009-11-20 09:32:46 -0800561void AwesomePlayer::onStreamDone() {
562 // Posted whenever any stream finishes playing.
563
564 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -0800565 if (!mStreamDoneEventPending) {
566 return;
567 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800568 mStreamDoneEventPending = false;
569
Andreas Huber971305d2010-07-07 13:35:27 -0700570 if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
571 LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
572
573 notifyListener_l(
574 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
575
576 pause_l();
577
578 mFlags |= AT_EOS;
579 return;
580 }
581
582 const bool allDone =
583 (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
584 && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
585
586 if (!allDone) {
587 return;
588 }
589
590 if (mFlags & LOOPING) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800591 seekTo_l(0);
592
Andreas Huber7085b6842010-02-03 16:02:02 -0800593 if (mVideoSource != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800594 postVideoEvent_l();
595 }
596 } else {
Andreas Huber971305d2010-07-07 13:35:27 -0700597 LOGV("MEDIA_PLAYBACK_COMPLETE");
598 notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -0800599
600 pause_l();
Andreas Huber406a18b2010-02-18 16:45:13 -0800601
602 mFlags |= AT_EOS;
Andreas Huber27366fc2009-11-20 09:32:46 -0800603 }
604}
605
606status_t AwesomePlayer::play() {
607 Mutex::Autolock autoLock(mLock);
Andreas Huber4d61f602010-06-10 11:17:50 -0700608
609 mFlags &= ~CACHE_UNDERRUN;
610
Andreas Huberba7ec912010-02-12 10:42:02 -0800611 return play_l();
612}
Andreas Huber27366fc2009-11-20 09:32:46 -0800613
Andreas Huberba7ec912010-02-12 10:42:02 -0800614status_t AwesomePlayer::play_l() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800615 if (mFlags & PLAYING) {
616 return OK;
617 }
618
Andreas Huberffdf4782010-02-09 14:05:43 -0800619 if (!(mFlags & PREPARED)) {
620 status_t err = prepare_l();
621
622 if (err != OK) {
623 return err;
624 }
625 }
626
Andreas Huber27366fc2009-11-20 09:32:46 -0800627 mFlags |= PLAYING;
628 mFlags |= FIRST_FRAME;
629
Andreas Huberc1d5c922009-12-10 15:49:04 -0800630 bool deferredAudioSeek = false;
631
Andreas Huber27366fc2009-11-20 09:32:46 -0800632 if (mAudioSource != NULL) {
633 if (mAudioPlayer == NULL) {
634 if (mAudioSink != NULL) {
635 mAudioPlayer = new AudioPlayer(mAudioSink);
Andreas Huber27366fc2009-11-20 09:32:46 -0800636 mAudioPlayer->setSource(mAudioSource);
Andreas Huberdc9927d2010-03-08 15:46:13 -0800637
638 // We've already started the MediaSource in order to enable
639 // the prefetcher to read its data.
640 status_t err = mAudioPlayer->start(
641 true /* sourceAlreadyStarted */);
Andreas Huber62eac002010-01-29 13:24:58 -0800642
643 if (err != OK) {
644 delete mAudioPlayer;
645 mAudioPlayer = NULL;
646
647 mFlags &= ~(PLAYING | FIRST_FRAME);
648
649 return err;
650 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800651
Andreas Huber27366fc2009-11-20 09:32:46 -0800652 mTimeSource = mAudioPlayer;
653
Andreas Huberc1d5c922009-12-10 15:49:04 -0800654 deferredAudioSeek = true;
Andreas Huber70d10c02010-02-03 11:37:29 -0800655
656 mWatchForAudioSeekComplete = false;
657 mWatchForAudioEOS = true;
Andreas Huber27366fc2009-11-20 09:32:46 -0800658 }
659 } else {
660 mAudioPlayer->resume();
661 }
Andreas Huber70d10c02010-02-03 11:37:29 -0800662
663 postCheckAudioStatusEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800664 }
665
666 if (mTimeSource == NULL && mAudioPlayer == NULL) {
Andreas Huber971305d2010-07-07 13:35:27 -0700667 mTimeSource = &mSystemTimeSource;
Andreas Huber27366fc2009-11-20 09:32:46 -0800668 }
669
670 if (mVideoSource != NULL) {
Andreas Huber7085b6842010-02-03 16:02:02 -0800671 // Kick off video playback
672 postVideoEvent_l();
Andreas Huber27366fc2009-11-20 09:32:46 -0800673 }
674
Andreas Huberc1d5c922009-12-10 15:49:04 -0800675 if (deferredAudioSeek) {
676 // If there was a seek request while we were paused
677 // and we're just starting up again, honor the request now.
678 seekAudioIfNecessary_l();
679 }
680
Andreas Huber406a18b2010-02-18 16:45:13 -0800681 if (mFlags & AT_EOS) {
682 // Legacy behaviour, if a stream finishes playing and then
683 // is started again, we play from the start...
684 seekTo_l(0);
685 }
686
Andreas Huber27366fc2009-11-20 09:32:46 -0800687 return OK;
688}
689
690void AwesomePlayer::initRenderer_l() {
691 if (mISurface != NULL) {
692 sp<MetaData> meta = mVideoSource->getFormat();
693
694 int32_t format;
695 const char *component;
696 int32_t decodedWidth, decodedHeight;
697 CHECK(meta->findInt32(kKeyColorFormat, &format));
698 CHECK(meta->findCString(kKeyDecoderComponent, &component));
699 CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
700 CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
701
Andreas Hubera67d5382009-12-10 15:32:12 -0800702 mVideoRenderer.clear();
703
704 // Must ensure that mVideoRenderer's destructor is actually executed
705 // before creating a new one.
706 IPCThreadState::self()->flushCommands();
707
Andreas Huber1314e732009-12-14 14:18:22 -0800708 if (!strncmp("OMX.", component, 4)) {
709 // Our OMX codecs allocate buffers on the media_server side
710 // therefore they require a remote IOMXRenderer that knows how
711 // to display them.
712 mVideoRenderer = new AwesomeRemoteRenderer(
713 mClient.interface()->createRenderer(
714 mISurface, component,
715 (OMX_COLOR_FORMATTYPE)format,
716 decodedWidth, decodedHeight,
717 mVideoWidth, mVideoHeight));
718 } else {
719 // Other decoders are instantiated locally and as a consequence
720 // allocate their buffers in local address space.
721 mVideoRenderer = new AwesomeLocalRenderer(
Andreas Huber7b73cfc2010-02-12 14:40:08 -0800722 false, // previewOnly
Andreas Huber4ab5a6f2010-02-11 11:00:26 -0800723 component,
Andreas Huber1314e732009-12-14 14:18:22 -0800724 (OMX_COLOR_FORMATTYPE)format,
725 mISurface,
726 mVideoWidth, mVideoHeight,
727 decodedWidth, decodedHeight);
728 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800729 }
730}
731
732status_t AwesomePlayer::pause() {
733 Mutex::Autolock autoLock(mLock);
Andreas Huber4d61f602010-06-10 11:17:50 -0700734
735 mFlags &= ~CACHE_UNDERRUN;
736
Andreas Huber27366fc2009-11-20 09:32:46 -0800737 return pause_l();
738}
739
740status_t AwesomePlayer::pause_l() {
741 if (!(mFlags & PLAYING)) {
742 return OK;
743 }
744
Andreas Huberb9e63832010-01-26 16:20:10 -0800745 cancelPlayerEvents(true /* keepBufferingGoing */);
Andreas Huber27366fc2009-11-20 09:32:46 -0800746
747 if (mAudioPlayer != NULL) {
748 mAudioPlayer->pause();
749 }
750
751 mFlags &= ~PLAYING;
752
753 return OK;
754}
755
756bool AwesomePlayer::isPlaying() const {
Andreas Huber4d61f602010-06-10 11:17:50 -0700757 return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
Andreas Huber27366fc2009-11-20 09:32:46 -0800758}
759
760void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
761 Mutex::Autolock autoLock(mLock);
762
763 mISurface = isurface;
764}
765
766void AwesomePlayer::setAudioSink(
767 const sp<MediaPlayerBase::AudioSink> &audioSink) {
768 Mutex::Autolock autoLock(mLock);
769
770 mAudioSink = audioSink;
771}
772
773status_t AwesomePlayer::setLooping(bool shouldLoop) {
774 Mutex::Autolock autoLock(mLock);
775
776 mFlags = mFlags & ~LOOPING;
777
778 if (shouldLoop) {
779 mFlags |= LOOPING;
780 }
781
782 return OK;
783}
784
785status_t AwesomePlayer::getDuration(int64_t *durationUs) {
Andreas Huber252573c2010-03-26 10:17:17 -0700786 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800787
788 if (mDurationUs < 0) {
789 return UNKNOWN_ERROR;
790 }
791
792 *durationUs = mDurationUs;
793
794 return OK;
795}
796
797status_t AwesomePlayer::getPosition(int64_t *positionUs) {
Andreas Hubereeb97d92010-08-27 13:29:08 -0700798 if (mRTSPController != NULL) {
799 *positionUs = mRTSPController->getNormalPlayTimeUs();
800 }
801 else if (mSeeking) {
Andreas Huberddb709c2010-04-07 10:24:35 -0700802 *positionUs = mSeekTimeUs;
803 } else if (mVideoSource != NULL) {
Andreas Huber252573c2010-03-26 10:17:17 -0700804 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800805 *positionUs = mVideoTimeUs;
806 } else if (mAudioPlayer != NULL) {
807 *positionUs = mAudioPlayer->getMediaTimeUs();
808 } else {
809 *positionUs = 0;
810 }
811
812 return OK;
813}
814
815status_t AwesomePlayer::seekTo(int64_t timeUs) {
Andreas Huber62f7ffe2010-05-06 10:18:05 -0700816 if (mExtractorFlags
817 & (MediaExtractor::CAN_SEEK_FORWARD
818 | MediaExtractor::CAN_SEEK_BACKWARD)) {
819 Mutex::Autolock autoLock(mLock);
820 return seekTo_l(timeUs);
821 }
822
823 return OK;
Andreas Huber27366fc2009-11-20 09:32:46 -0800824}
825
826status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
Andreas Hubere0dd7d32010-08-24 14:33:58 -0700827 if (mRTSPController != NULL) {
Andreas Hubere0dd7d32010-08-24 14:33:58 -0700828 mRTSPController->seek(timeUs);
Andreas Hubere0dd7d32010-08-24 14:33:58 -0700829
830 notifyListener_l(MEDIA_SEEK_COMPLETE);
831 mSeekNotificationSent = true;
Andreas Hubere0dd7d32010-08-24 14:33:58 -0700832 return OK;
833 }
834
Andreas Huber4d61f602010-06-10 11:17:50 -0700835 if (mFlags & CACHE_UNDERRUN) {
836 mFlags &= ~CACHE_UNDERRUN;
837 play_l();
838 }
839
Andreas Huber27366fc2009-11-20 09:32:46 -0800840 mSeeking = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700841 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800842 mSeekTimeUs = timeUs;
Andreas Huber971305d2010-07-07 13:35:27 -0700843 mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
Andreas Huber27366fc2009-11-20 09:32:46 -0800844
845 seekAudioIfNecessary_l();
846
Andreas Huber8e2b9412010-03-31 09:40:15 -0700847 if (!(mFlags & PLAYING)) {
848 LOGV("seeking while paused, sending SEEK_COMPLETE notification"
849 " immediately.");
850
851 notifyListener_l(MEDIA_SEEK_COMPLETE);
852 mSeekNotificationSent = true;
853 }
854
Andreas Huber27366fc2009-11-20 09:32:46 -0800855 return OK;
856}
857
858void AwesomePlayer::seekAudioIfNecessary_l() {
Andreas Huber7085b6842010-02-03 16:02:02 -0800859 if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
Andreas Huber27366fc2009-11-20 09:32:46 -0800860 mAudioPlayer->seekTo(mSeekTimeUs);
861
Andreas Huber70d10c02010-02-03 11:37:29 -0800862 mWatchForAudioSeekComplete = true;
863 mWatchForAudioEOS = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -0700864 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -0800865 }
866}
867
868status_t AwesomePlayer::getVideoDimensions(
869 int32_t *width, int32_t *height) const {
870 Mutex::Autolock autoLock(mLock);
871
872 if (mVideoWidth < 0 || mVideoHeight < 0) {
873 return UNKNOWN_ERROR;
874 }
875
876 *width = mVideoWidth;
877 *height = mVideoHeight;
878
879 return OK;
880}
881
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800882void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
883 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -0800884
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800885 mAudioTrack = source;
886}
887
888status_t AwesomePlayer::initAudioDecoder() {
889 sp<MetaData> meta = mAudioTrack->getFormat();
Andreas Huberc79827a2010-01-05 10:54:55 -0800890
891 const char *mime;
892 CHECK(meta->findCString(kKeyMIMEType, &mime));
893
894 if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800895 mAudioSource = mAudioTrack;
Andreas Huberc79827a2010-01-05 10:54:55 -0800896 } else {
897 mAudioSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800898 mClient.interface(), mAudioTrack->getFormat(),
Andreas Huberc79827a2010-01-05 10:54:55 -0800899 false, // createEncoder
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800900 mAudioTrack);
Andreas Huberc79827a2010-01-05 10:54:55 -0800901 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800902
903 if (mAudioSource != NULL) {
904 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800905 if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -0700906 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800907 if (mDurationUs < 0 || durationUs > mDurationUs) {
908 mDurationUs = durationUs;
909 }
910 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800911
Andreas Huber3c78a1b2010-05-13 09:15:21 -0700912 status_t err = mAudioSource->start();
913
914 if (err != OK) {
915 mAudioSource.clear();
916 return err;
917 }
Andreas Huberd0332ad2010-04-12 16:05:57 -0700918 } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
919 // For legacy reasons we're simply going to ignore the absence
920 // of an audio decoder for QCELP instead of aborting playback
921 // altogether.
922 return OK;
923 }
Andreas Huberdc9927d2010-03-08 15:46:13 -0800924
Andreas Huber27366fc2009-11-20 09:32:46 -0800925 return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
926}
927
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800928void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
929 CHECK(source != NULL);
Andreas Huber27366fc2009-11-20 09:32:46 -0800930
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800931 mVideoTrack = source;
932}
933
934status_t AwesomePlayer::initVideoDecoder() {
Andreas Huber57648e42010-08-04 10:14:30 -0700935 uint32_t flags = 0;
Andreas Huber27366fc2009-11-20 09:32:46 -0800936 mVideoSource = OMXCodec::Create(
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800937 mClient.interface(), mVideoTrack->getFormat(),
Andreas Huber27366fc2009-11-20 09:32:46 -0800938 false, // createEncoder
Andreas Huber57648e42010-08-04 10:14:30 -0700939 mVideoTrack,
940 NULL, flags);
Andreas Huber27366fc2009-11-20 09:32:46 -0800941
942 if (mVideoSource != NULL) {
943 int64_t durationUs;
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800944 if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
Andreas Huber252573c2010-03-26 10:17:17 -0700945 Mutex::Autolock autoLock(mMiscStateLock);
Andreas Huber27366fc2009-11-20 09:32:46 -0800946 if (mDurationUs < 0 || durationUs > mDurationUs) {
947 mDurationUs = durationUs;
948 }
949 }
950
Andreas Huber3ac94ef2010-03-05 10:42:10 -0800951 CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
952 CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
Andreas Huber27366fc2009-11-20 09:32:46 -0800953
Andreas Huber1919e5a2010-05-20 10:37:06 -0700954 status_t err = mVideoSource->start();
955
956 if (err != OK) {
957 mVideoSource.clear();
958 return err;
959 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800960 }
961
962 return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
963}
964
Andreas Huber6be780e2010-02-08 14:40:30 -0800965void AwesomePlayer::onVideoEvent() {
Andreas Huber27366fc2009-11-20 09:32:46 -0800966 Mutex::Autolock autoLock(mLock);
Andreas Huberba7ec912010-02-12 10:42:02 -0800967 if (!mVideoEventPending) {
968 // The event has been cancelled in reset_l() but had already
969 // been scheduled for execution at that time.
970 return;
971 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800972 mVideoEventPending = false;
973
974 if (mSeeking) {
975 if (mLastVideoBuffer) {
976 mLastVideoBuffer->release();
977 mLastVideoBuffer = NULL;
978 }
979
980 if (mVideoBuffer) {
981 mVideoBuffer->release();
982 mVideoBuffer = NULL;
983 }
Andreas Huber4d61f602010-06-10 11:17:50 -0700984
985 if (mCachedSource != NULL && mAudioSource != NULL) {
986 // We're going to seek the video source first, followed by
987 // the audio source.
988 // In order to avoid jumps in the DataSource offset caused by
989 // the audio codec prefetching data from the old locations
990 // while the video codec is already reading data from the new
991 // locations, we'll "pause" the audio source, causing it to
992 // stop reading input data until a subsequent seek.
993
994 if (mAudioPlayer != NULL) {
995 mAudioPlayer->pause();
996 }
997 mAudioSource->pause();
998 }
Andreas Huber27366fc2009-11-20 09:32:46 -0800999 }
1000
1001 if (!mVideoBuffer) {
1002 MediaSource::ReadOptions options;
1003 if (mSeeking) {
1004 LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
1005
Andreas Huber6624c9f2010-07-20 15:04:28 -07001006 options.setSeekTo(
1007 mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
Andreas Huber27366fc2009-11-20 09:32:46 -08001008 }
1009 for (;;) {
1010 status_t err = mVideoSource->read(&mVideoBuffer, &options);
Andreas Huberb1f5ee42009-12-14 15:34:11 -08001011 options.clearSeekTo();
Andreas Huber27366fc2009-11-20 09:32:46 -08001012
1013 if (err != OK) {
1014 CHECK_EQ(mVideoBuffer, NULL);
1015
1016 if (err == INFO_FORMAT_CHANGED) {
1017 LOGV("VideoSource signalled format change.");
1018
Andreas Huber7085b6842010-02-03 16:02:02 -08001019 if (mVideoRenderer != NULL) {
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001020 mVideoRendererIsPreview = false;
Andreas Huber7085b6842010-02-03 16:02:02 -08001021 initRenderer_l();
1022 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001023 continue;
1024 }
1025
Andreas Huber971305d2010-07-07 13:35:27 -07001026 mFlags |= VIDEO_AT_EOS;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001027 postStreamDoneEvent_l(err);
Andreas Huber27366fc2009-11-20 09:32:46 -08001028 return;
1029 }
1030
Andreas Hubera67d5382009-12-10 15:32:12 -08001031 if (mVideoBuffer->range_length() == 0) {
Andreas Huber6ddcf012009-12-10 15:32:12 -08001032 // Some decoders, notably the PV AVC software decoder
1033 // return spurious empty buffers that we just want to ignore.
1034
Andreas Hubera67d5382009-12-10 15:32:12 -08001035 mVideoBuffer->release();
1036 mVideoBuffer = NULL;
1037 continue;
1038 }
1039
Andreas Huber27366fc2009-11-20 09:32:46 -08001040 break;
1041 }
1042 }
1043
1044 int64_t timeUs;
1045 CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1046
Andreas Huber252573c2010-03-26 10:17:17 -07001047 {
1048 Mutex::Autolock autoLock(mMiscStateLock);
1049 mVideoTimeUs = timeUs;
1050 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001051
1052 if (mSeeking) {
1053 if (mAudioPlayer != NULL) {
1054 LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
1055
1056 mAudioPlayer->seekTo(timeUs);
Andreas Huber4d61f602010-06-10 11:17:50 -07001057 mAudioPlayer->resume();
Andreas Huber70d10c02010-02-03 11:37:29 -08001058 mWatchForAudioSeekComplete = true;
1059 mWatchForAudioEOS = true;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001060 } else if (!mSeekNotificationSent) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001061 // If we're playing video only, report seek complete now,
1062 // otherwise audio player will notify us later.
Andreas Hubera3f43842010-01-21 10:28:45 -08001063 notifyListener_l(MEDIA_SEEK_COMPLETE);
Andreas Huber27366fc2009-11-20 09:32:46 -08001064 }
1065
1066 mFlags |= FIRST_FRAME;
1067 mSeeking = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001068 mSeekNotificationSent = false;
Andreas Huber27366fc2009-11-20 09:32:46 -08001069 }
1070
Andreas Huber971305d2010-07-07 13:35:27 -07001071 TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
1072
Andreas Huber27366fc2009-11-20 09:32:46 -08001073 if (mFlags & FIRST_FRAME) {
1074 mFlags &= ~FIRST_FRAME;
1075
Andreas Huber971305d2010-07-07 13:35:27 -07001076 mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
Andreas Huber27366fc2009-11-20 09:32:46 -08001077 }
1078
1079 int64_t realTimeUs, mediaTimeUs;
Andreas Huber971305d2010-07-07 13:35:27 -07001080 if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
Andreas Huber27366fc2009-11-20 09:32:46 -08001081 && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1082 mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1083 }
1084
Andreas Huber971305d2010-07-07 13:35:27 -07001085 int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
Andreas Huber27366fc2009-11-20 09:32:46 -08001086
1087 int64_t latenessUs = nowUs - timeUs;
1088
Andreas Huberf88f8442010-08-10 11:18:36 -07001089 if (mRTPSession != NULL) {
1090 // We'll completely ignore timestamps for gtalk videochat
1091 // and we'll play incoming video as fast as we get it.
1092 latenessUs = 0;
1093 }
1094
Andreas Huber24b0a952009-11-23 14:02:00 -08001095 if (latenessUs > 40000) {
1096 // We're more than 40ms late.
Andreas Huber4a9375e2010-02-09 11:54:33 -08001097 LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
Andreas Huber27366fc2009-11-20 09:32:46 -08001098
1099 mVideoBuffer->release();
1100 mVideoBuffer = NULL;
1101
1102 postVideoEvent_l();
1103 return;
1104 }
1105
1106 if (latenessUs < -10000) {
1107 // We're more than 10ms early.
1108
1109 postVideoEvent_l(10000);
1110 return;
1111 }
1112
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001113 if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
1114 mVideoRendererIsPreview = false;
1115
Andreas Huber7085b6842010-02-03 16:02:02 -08001116 initRenderer_l();
1117 }
1118
1119 if (mVideoRenderer != NULL) {
1120 mVideoRenderer->render(mVideoBuffer);
1121 }
Andreas Huber27366fc2009-11-20 09:32:46 -08001122
1123 if (mLastVideoBuffer) {
1124 mLastVideoBuffer->release();
1125 mLastVideoBuffer = NULL;
1126 }
1127 mLastVideoBuffer = mVideoBuffer;
1128 mVideoBuffer = NULL;
1129
1130 postVideoEvent_l();
1131}
1132
1133void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
1134 if (mVideoEventPending) {
1135 return;
1136 }
1137
1138 mVideoEventPending = true;
1139 mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1140}
1141
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001142void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
Andreas Huber27366fc2009-11-20 09:32:46 -08001143 if (mStreamDoneEventPending) {
1144 return;
1145 }
1146 mStreamDoneEventPending = true;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001147
1148 mStreamDoneStatus = status;
Andreas Huber27366fc2009-11-20 09:32:46 -08001149 mQueue.postEvent(mStreamDoneEvent);
1150}
1151
Andreas Huberb9e63832010-01-26 16:20:10 -08001152void AwesomePlayer::postBufferingEvent_l() {
Andreas Huberb9e63832010-01-26 16:20:10 -08001153 if (mBufferingEventPending) {
1154 return;
1155 }
1156 mBufferingEventPending = true;
1157 mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1158}
1159
Andreas Huber70d10c02010-02-03 11:37:29 -08001160void AwesomePlayer::postCheckAudioStatusEvent_l() {
1161 if (mAudioStatusEventPending) {
1162 return;
1163 }
1164 mAudioStatusEventPending = true;
1165 mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll);
1166}
1167
1168void AwesomePlayer::onCheckAudioStatus() {
1169 Mutex::Autolock autoLock(mLock);
Andreas Huberc0178f12010-02-17 15:58:57 -08001170 if (!mAudioStatusEventPending) {
1171 // Event was dispatched and while we were blocking on the mutex,
1172 // has already been cancelled.
1173 return;
1174 }
1175
Andreas Huber70d10c02010-02-03 11:37:29 -08001176 mAudioStatusEventPending = false;
1177
1178 if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1179 mWatchForAudioSeekComplete = false;
Andreas Huber8e2b9412010-03-31 09:40:15 -07001180
1181 if (!mSeekNotificationSent) {
1182 notifyListener_l(MEDIA_SEEK_COMPLETE);
1183 mSeekNotificationSent = true;
1184 }
Andreas Huberddb709c2010-04-07 10:24:35 -07001185
1186 mSeeking = false;
Andreas Huber70d10c02010-02-03 11:37:29 -08001187 }
1188
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001189 status_t finalStatus;
1190 if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
Andreas Huber70d10c02010-02-03 11:37:29 -08001191 mWatchForAudioEOS = false;
Andreas Huber971305d2010-07-07 13:35:27 -07001192 mFlags |= AUDIO_AT_EOS;
1193 mFlags |= FIRST_FRAME;
Andreas Huberd7d22eb2010-02-23 13:45:33 -08001194 postStreamDoneEvent_l(finalStatus);
Andreas Huber70d10c02010-02-03 11:37:29 -08001195 }
1196
1197 postCheckAudioStatusEvent_l();
1198}
1199
Andreas Huber6be780e2010-02-08 14:40:30 -08001200status_t AwesomePlayer::prepare() {
1201 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001202 return prepare_l();
1203}
Andreas Huber6be780e2010-02-08 14:40:30 -08001204
Andreas Huberffdf4782010-02-09 14:05:43 -08001205status_t AwesomePlayer::prepare_l() {
1206 if (mFlags & PREPARED) {
1207 return OK;
1208 }
1209
1210 if (mFlags & PREPARING) {
1211 return UNKNOWN_ERROR;
1212 }
1213
1214 mIsAsyncPrepare = false;
Andreas Huber6be780e2010-02-08 14:40:30 -08001215 status_t err = prepareAsync_l();
1216
1217 if (err != OK) {
1218 return err;
1219 }
1220
Andreas Huberffdf4782010-02-09 14:05:43 -08001221 while (mFlags & PREPARING) {
Andreas Huber6be780e2010-02-08 14:40:30 -08001222 mPreparedCondition.wait(mLock);
1223 }
1224
Andreas Huberffdf4782010-02-09 14:05:43 -08001225 return mPrepareResult;
Andreas Huber6be780e2010-02-08 14:40:30 -08001226}
1227
1228status_t AwesomePlayer::prepareAsync() {
1229 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001230
1231 if (mFlags & PREPARING) {
1232 return UNKNOWN_ERROR; // async prepare already pending
1233 }
1234
1235 mIsAsyncPrepare = true;
Andreas Huber6be780e2010-02-08 14:40:30 -08001236 return prepareAsync_l();
1237}
1238
1239status_t AwesomePlayer::prepareAsync_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001240 if (mFlags & PREPARING) {
1241 return UNKNOWN_ERROR; // async prepare already pending
Andreas Huber6be780e2010-02-08 14:40:30 -08001242 }
1243
Andreas Huber406a18b2010-02-18 16:45:13 -08001244 if (!mQueueStarted) {
1245 mQueue.start();
1246 mQueueStarted = true;
1247 }
1248
Andreas Huberffdf4782010-02-09 14:05:43 -08001249 mFlags |= PREPARING;
Andreas Huber6be780e2010-02-08 14:40:30 -08001250 mAsyncPrepareEvent = new AwesomeEvent(
1251 this, &AwesomePlayer::onPrepareAsyncEvent);
1252
1253 mQueue.postEvent(mAsyncPrepareEvent);
1254
1255 return OK;
1256}
1257
Andreas Huberffdf4782010-02-09 14:05:43 -08001258status_t AwesomePlayer::finishSetDataSource_l() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001259 sp<DataSource> dataSource;
1260
1261 if (!strncasecmp("http://", mUri.string(), 7)) {
Andreas Huber4d61f602010-06-10 11:17:50 -07001262 mConnectingDataSource = new NuHTTPDataSource;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001263
1264 mLock.unlock();
Andreas Huber3a53dc52010-06-11 09:57:46 -07001265 status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001266 mLock.lock();
1267
1268 if (err != OK) {
1269 mConnectingDataSource.clear();
1270
1271 LOGI("mConnectingDataSource->connect() returned %d", err);
1272 return err;
1273 }
1274
Andreas Huber4d61f602010-06-10 11:17:50 -07001275#if 0
1276 mCachedSource = new NuCachedSource2(
1277 new ThrottledSource(
1278 mConnectingDataSource, 50 * 1024 /* bytes/sec */));
1279#else
1280 mCachedSource = new NuCachedSource2(mConnectingDataSource);
1281#endif
Andreas Huberedbb4d82010-03-12 08:59:22 -08001282 mConnectingDataSource.clear();
Andreas Huber4d61f602010-06-10 11:17:50 -07001283
1284 dataSource = mCachedSource;
Andreas Huber202348e2010-06-07 14:35:29 -07001285 } else if (!strncasecmp(mUri.string(), "httplive://", 11)) {
1286 String8 uri("http://");
1287 uri.append(mUri.string() + 11);
1288
1289 dataSource = new LiveSource(uri.string());
1290
Andreas Huber4d61f602010-06-10 11:17:50 -07001291 mCachedSource = new NuCachedSource2(dataSource);
1292 dataSource = mCachedSource;
Andreas Huber202348e2010-06-07 14:35:29 -07001293
1294 sp<MediaExtractor> extractor =
1295 MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
Andreas Huber4d61f602010-06-10 11:17:50 -07001296
1297 return setDataSource_l(extractor);
Mike Dodd8741dfa2010-08-12 16:04:35 -07001298 } else if (!strncmp("rtsp://gtalk/", mUri.string(), 13)) {
Andreas Huber57648e42010-08-04 10:14:30 -07001299 if (mLooper == NULL) {
1300 mLooper = new ALooper;
Andreas Huberc4e0b702010-08-27 15:21:07 -07001301 mLooper->setName("gtalk rtp");
Andreas Huber3eaa3002010-08-05 09:22:25 -07001302 mLooper->start(
1303 false /* runOnCallingThread */,
1304 false /* canCallJava */,
1305 PRIORITY_HIGHEST);
Andreas Huber57648e42010-08-04 10:14:30 -07001306 }
1307
Mike Dodd8741dfa2010-08-12 16:04:35 -07001308 const char *startOfCodecString = &mUri.string()[13];
1309 const char *startOfSlash1 = strchr(startOfCodecString, '/');
1310 if (startOfSlash1 == NULL) {
1311 return BAD_VALUE;
1312 }
1313 const char *startOfWidthString = &startOfSlash1[1];
1314 const char *startOfSlash2 = strchr(startOfWidthString, '/');
1315 if (startOfSlash2 == NULL) {
1316 return BAD_VALUE;
1317 }
1318 const char *startOfHeightString = &startOfSlash2[1];
1319
1320 String8 codecString(startOfCodecString, startOfSlash1 - startOfCodecString);
1321 String8 widthString(startOfWidthString, startOfSlash2 - startOfWidthString);
1322 String8 heightString(startOfHeightString);
1323
Andreas Huber57648e42010-08-04 10:14:30 -07001324#if 0
1325 mRTPPusher = new UDPPusher("/data/misc/rtpout.bin", 5434);
1326 mLooper->registerHandler(mRTPPusher);
1327
1328 mRTCPPusher = new UDPPusher("/data/misc/rtcpout.bin", 5435);
1329 mLooper->registerHandler(mRTCPPusher);
1330#endif
1331
1332 mRTPSession = new ARTPSession;
1333 mLooper->registerHandler(mRTPSession);
1334
1335#if 0
Andreas Huber57648e42010-08-04 10:14:30 -07001336 // My AMR SDP
1337 static const char *raw =
1338 "v=0\r\n"
1339 "o=- 64 233572944 IN IP4 127.0.0.0\r\n"
1340 "s=QuickTime\r\n"
1341 "t=0 0\r\n"
1342 "a=range:npt=0-315\r\n"
1343 "a=isma-compliance:2,2.0,2\r\n"
1344 "m=audio 5434 RTP/AVP 97\r\n"
1345 "c=IN IP4 127.0.0.1\r\n"
1346 "b=AS:30\r\n"
1347 "a=rtpmap:97 AMR/8000/1\r\n"
1348 "a=fmtp:97 octet-align\r\n";
1349#elif 1
Mike Dodd8741dfa2010-08-12 16:04:35 -07001350 String8 sdp;
1351 sdp.appendFormat(
Andreas Huber57648e42010-08-04 10:14:30 -07001352 "v=0\r\n"
1353 "o=- 64 233572944 IN IP4 127.0.0.0\r\n"
1354 "s=QuickTime\r\n"
1355 "t=0 0\r\n"
1356 "a=range:npt=0-315\r\n"
1357 "a=isma-compliance:2,2.0,2\r\n"
1358 "m=video 5434 RTP/AVP 97\r\n"
1359 "c=IN IP4 127.0.0.1\r\n"
1360 "b=AS:30\r\n"
Mike Dodd8741dfa2010-08-12 16:04:35 -07001361 "a=rtpmap:97 %s/90000\r\n"
1362 "a=cliprect:0,0,%s,%s\r\n"
1363 "a=framesize:97 %s-%s\r\n",
1364
1365 codecString.string(),
1366 heightString.string(), widthString.string(),
1367 widthString.string(), heightString.string()
1368 );
1369 const char *raw = sdp.string();
1370
Andreas Huber57648e42010-08-04 10:14:30 -07001371#endif
1372
1373 sp<ASessionDescription> desc = new ASessionDescription;
1374 CHECK(desc->setTo(raw, strlen(raw)));
1375
1376 CHECK_EQ(mRTPSession->setup(desc), (status_t)OK);
1377
1378 if (mRTPPusher != NULL) {
1379 mRTPPusher->start();
1380 }
1381
1382 if (mRTCPPusher != NULL) {
1383 mRTCPPusher->start();
1384 }
1385
1386 CHECK_EQ(mRTPSession->countTracks(), 1u);
1387 sp<MediaSource> source = mRTPSession->trackAt(0);
1388
1389#if 0
1390 bool eos;
1391 while (((APacketSource *)source.get())
1392 ->getQueuedDuration(&eos) < 5000000ll && !eos) {
1393 usleep(100000ll);
1394 }
1395#endif
1396
1397 const char *mime;
1398 CHECK(source->getFormat()->findCString(kKeyMIMEType, &mime));
1399
1400 if (!strncasecmp("video/", mime, 6)) {
1401 setVideoSource(source);
1402 } else {
1403 CHECK(!strncasecmp("audio/", mime, 6));
1404 setAudioSource(source);
1405 }
1406
1407 mExtractorFlags = MediaExtractor::CAN_PAUSE;
1408
1409 return OK;
Andreas Huber7a747b82010-06-07 15:19:40 -07001410 } else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
1411 if (mLooper == NULL) {
1412 mLooper = new ALooper;
Andreas Huberc4e0b702010-08-27 15:21:07 -07001413 mLooper->setName("rtsp");
Andreas Huber7a747b82010-06-07 15:19:40 -07001414 mLooper->start();
1415 }
1416 mRTSPController = new ARTSPController(mLooper);
1417 status_t err = mRTSPController->connect(mUri.string());
Andreas Huber202348e2010-06-07 14:35:29 -07001418
Andreas Huber7a747b82010-06-07 15:19:40 -07001419 LOGI("ARTSPController::connect returned %d", err);
1420
1421 if (err != OK) {
1422 mRTSPController.clear();
1423 return err;
1424 }
1425
1426 sp<MediaExtractor> extractor = mRTSPController.get();
Andreas Huber202348e2010-06-07 14:35:29 -07001427 return setDataSource_l(extractor);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001428 } else {
1429 dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1430 }
Andreas Huberffdf4782010-02-09 14:05:43 -08001431
1432 if (dataSource == NULL) {
1433 return UNKNOWN_ERROR;
1434 }
1435
1436 sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1437
1438 if (extractor == NULL) {
1439 return UNKNOWN_ERROR;
1440 }
1441
Andreas Huberffdf4782010-02-09 14:05:43 -08001442 return setDataSource_l(extractor);
1443}
1444
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001445void AwesomePlayer::abortPrepare(status_t err) {
1446 CHECK(err != OK);
1447
1448 if (mIsAsyncPrepare) {
1449 notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1450 }
1451
1452 mPrepareResult = err;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001453 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
Andreas Huber3ac94ef2010-03-05 10:42:10 -08001454 mAsyncPrepareEvent = NULL;
1455 mPreparedCondition.broadcast();
1456}
1457
Andreas Huberf71daba2010-03-24 09:24:40 -07001458// static
1459bool AwesomePlayer::ContinuePreparation(void *cookie) {
1460 AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
1461
1462 return (me->mFlags & PREPARE_CANCELLED) == 0;
1463}
1464
Andreas Huber6be780e2010-02-08 14:40:30 -08001465void AwesomePlayer::onPrepareAsyncEvent() {
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001466 Mutex::Autolock autoLock(mLock);
Andreas Huberffdf4782010-02-09 14:05:43 -08001467
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001468 if (mFlags & PREPARE_CANCELLED) {
1469 LOGI("prepare was cancelled before doing anything");
1470 abortPrepare(UNKNOWN_ERROR);
1471 return;
1472 }
1473
1474 if (mUri.size() > 0) {
1475 status_t err = finishSetDataSource_l();
1476
1477 if (err != OK) {
1478 abortPrepare(err);
Andreas Huberedbb4d82010-03-12 08:59:22 -08001479 return;
1480 }
Andreas Huber6be780e2010-02-08 14:40:30 -08001481 }
1482
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001483 if (mVideoTrack != NULL && mVideoSource == NULL) {
1484 status_t err = initVideoDecoder();
Andreas Huber6be780e2010-02-08 14:40:30 -08001485
Andreas Huber87ab9cd2010-09-03 13:20:33 -07001486 if (err != OK) {
1487 abortPrepare(err);
1488 return;
1489 }
1490 }
1491
1492 if (mAudioTrack != NULL && mAudioSource == NULL) {
1493 status_t err = initAudioDecoder();
1494
1495 if (err != OK) {
1496 abortPrepare(err);
1497 return;
1498 }
1499 }
1500
1501 if (mCachedSource != NULL || mRTSPController != NULL) {
1502 postBufferingEvent_l();
1503 } else {
1504 finishAsyncPrepare_l();
1505 }
1506}
1507
1508void AwesomePlayer::finishAsyncPrepare_l() {
Andreas Huberffdf4782010-02-09 14:05:43 -08001509 if (mIsAsyncPrepare) {
1510 if (mVideoWidth < 0 || mVideoHeight < 0) {
1511 notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1512 } else {
1513 notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
1514 }
1515
1516 notifyListener_l(MEDIA_PREPARED);
Andreas Huber6be780e2010-02-08 14:40:30 -08001517 }
1518
Andreas Huberffdf4782010-02-09 14:05:43 -08001519 mPrepareResult = OK;
Andreas Huberedbb4d82010-03-12 08:59:22 -08001520 mFlags &= ~(PREPARING|PREPARE_CANCELLED);
Andreas Huberffdf4782010-02-09 14:05:43 -08001521 mFlags |= PREPARED;
Andreas Huber6be780e2010-02-08 14:40:30 -08001522 mAsyncPrepareEvent = NULL;
Andreas Huberffdf4782010-02-09 14:05:43 -08001523 mPreparedCondition.broadcast();
Andreas Huber6be780e2010-02-08 14:40:30 -08001524}
1525
Andreas Huberba7ec912010-02-12 10:42:02 -08001526status_t AwesomePlayer::suspend() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001527 LOGV("suspend");
Andreas Huberba7ec912010-02-12 10:42:02 -08001528 Mutex::Autolock autoLock(mLock);
1529
1530 if (mSuspensionState != NULL) {
Gloria Wangb19da8e2010-04-12 17:13:06 -07001531 if (mLastVideoBuffer == NULL) {
1532 //go into here if video is suspended again
1533 //after resuming without being played between
1534 //them
1535 SuspensionState *state = mSuspensionState;
1536 mSuspensionState = NULL;
1537 reset_l();
1538 mSuspensionState = state;
1539 return OK;
1540 }
1541
1542 delete mSuspensionState;
1543 mSuspensionState = NULL;
Andreas Huberba7ec912010-02-12 10:42:02 -08001544 }
1545
Andreas Huberedbb4d82010-03-12 08:59:22 -08001546 if (mFlags & PREPARING) {
1547 mFlags |= PREPARE_CANCELLED;
1548 if (mConnectingDataSource != NULL) {
1549 LOGI("interrupting the connection process");
1550 mConnectingDataSource->disconnect();
1551 }
1552 }
1553
Andreas Huberba7ec912010-02-12 10:42:02 -08001554 while (mFlags & PREPARING) {
1555 mPreparedCondition.wait(mLock);
1556 }
1557
1558 SuspensionState *state = new SuspensionState;
1559 state->mUri = mUri;
1560 state->mUriHeaders = mUriHeaders;
1561 state->mFileSource = mFileSource;
1562
Andreas Huber406a18b2010-02-18 16:45:13 -08001563 state->mFlags = mFlags & (PLAYING | LOOPING | AT_EOS);
Andreas Huber252573c2010-03-26 10:17:17 -07001564 getPosition(&state->mPositionUs);
Andreas Huberba7ec912010-02-12 10:42:02 -08001565
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001566 if (mLastVideoBuffer) {
1567 size_t size = mLastVideoBuffer->range_length();
1568 if (size) {
1569 state->mLastVideoFrameSize = size;
1570 state->mLastVideoFrame = malloc(size);
1571 memcpy(state->mLastVideoFrame,
1572 (const uint8_t *)mLastVideoBuffer->data()
1573 + mLastVideoBuffer->range_offset(),
1574 size);
1575
1576 state->mVideoWidth = mVideoWidth;
1577 state->mVideoHeight = mVideoHeight;
1578
1579 sp<MetaData> meta = mVideoSource->getFormat();
1580 CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat));
1581 CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth));
1582 CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight));
1583 }
1584 }
1585
Andreas Huberba7ec912010-02-12 10:42:02 -08001586 reset_l();
1587
1588 mSuspensionState = state;
1589
1590 return OK;
1591}
1592
1593status_t AwesomePlayer::resume() {
Andreas Huberedbb4d82010-03-12 08:59:22 -08001594 LOGV("resume");
Andreas Huberba7ec912010-02-12 10:42:02 -08001595 Mutex::Autolock autoLock(mLock);
1596
1597 if (mSuspensionState == NULL) {
1598 return INVALID_OPERATION;
1599 }
1600
1601 SuspensionState *state = mSuspensionState;
1602 mSuspensionState = NULL;
1603
1604 status_t err;
1605 if (state->mFileSource != NULL) {
1606 err = setDataSource_l(state->mFileSource);
1607
1608 if (err == OK) {
1609 mFileSource = state->mFileSource;
1610 }
1611 } else {
1612 err = setDataSource_l(state->mUri, &state->mUriHeaders);
1613 }
1614
1615 if (err != OK) {
1616 delete state;
1617 state = NULL;
1618
1619 return err;
1620 }
1621
1622 seekTo_l(state->mPositionUs);
1623
Andreas Huber406a18b2010-02-18 16:45:13 -08001624 mFlags = state->mFlags & (LOOPING | AT_EOS);
Andreas Huberba7ec912010-02-12 10:42:02 -08001625
Andreas Huber7b73cfc2010-02-12 14:40:08 -08001626 if (state->mLastVideoFrame && mISurface != NULL) {
1627 mVideoRenderer =
1628 new AwesomeLocalRenderer(
1629 true, // previewOnly
1630 "",
1631 (OMX_COLOR_FORMATTYPE)state->mColorFormat,
1632 mISurface,
1633 state->mVideoWidth,
1634 state->mVideoHeight,
1635 state->mDecodedWidth,
1636 state->mDecodedHeight);
1637
1638 mVideoRendererIsPreview = true;
1639
1640 ((AwesomeLocalRenderer *)mVideoRenderer.get())->render(
1641 state->mLastVideoFrame, state->mLastVideoFrameSize);
1642 }
1643
Andreas Huberba7ec912010-02-12 10:42:02 -08001644 if (state->mFlags & PLAYING) {
1645 play_l();
1646 }
1647
Gloria Wangb19da8e2010-04-12 17:13:06 -07001648 mSuspensionState = state;
Andreas Huberba7ec912010-02-12 10:42:02 -08001649 state = NULL;
1650
1651 return OK;
1652}
1653
Andreas Huber62f7ffe2010-05-06 10:18:05 -07001654uint32_t AwesomePlayer::flags() const {
1655 return mExtractorFlags;
1656}
1657
Andreas Huber27366fc2009-11-20 09:32:46 -08001658} // namespace android
1659