AwesomePlayer.cpp revision d6119356f45c9c57cac812357d969ecc3001087e
122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/*
222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao * Copyright (C) 2009 The Android Open Source Project
322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *
422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao * Licensed under the Apache License, Version 2.0 (the "License");
522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao * you may not use this file except in compliance with the License.
622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao * You may obtain a copy of the License at
722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *
822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *      http://www.apache.org/licenses/LICENSE-2.0
987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *
1087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * Unless required by applicable law or agreed to in writing, software
1122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao * distributed under the License is distributed on an "AS IS" BASIS,
1222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao * See the License for the specific language governing permissions and
1422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao * limitations under the License.
15d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao */
1622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
1722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//#define LOG_NDEBUG 0
1822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#define LOG_TAG "AwesomePlayer"
1922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <utils/Log.h>
206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
2122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <dlfcn.h>
2222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
2322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "include/ARTSPController.h"
2422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "include/AwesomePlayer.h"
2522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "include/LiveSource.h"
2622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "include/SoftwareRenderer.h"
2722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "include/NuCachedSource2.h"
2822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "include/ThrottledSource.h"
2922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "include/MPEG2TSExtractor.h"
3022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "ARTPSession.h"
3222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "APacketSource.h"
3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "ASessionDescription.h"
3422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "UDPPusher.h"
3522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
3622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <binder/IPCThreadState.h>
376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <media/stagefright/AudioPlayer.h>
3822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/DataSource.h>
3922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/FileSource.h>
4022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/MediaBuffer.h>
4122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/MediaDefs.h>
4222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/MediaExtractor.h>
4322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/MediaDebug.h>
4422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/MediaSource.h>
4522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/MetaData.h>
4622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/OMXCodec.h>
4722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
4822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <surfaceflinger/Surface.h>
4922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
5022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <media/stagefright/foundation/ALooper.h>
5122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
5222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaonamespace android {
5322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
5422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaostatic int64_t kLowWaterMarkUs = 2000000ll;  // 2secs
5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaostatic int64_t kHighWaterMarkUs = 10000000ll;  // 10secs
5622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
57struct AwesomeEvent : public TimedEventQueue::Event {
58    AwesomeEvent(
59            AwesomePlayer *player,
60            void (AwesomePlayer::*method)())
61        : mPlayer(player),
62          mMethod(method) {
63    }
64
65protected:
66    virtual ~AwesomeEvent() {}
67
68    virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
69        (mPlayer->*mMethod)();
70    }
71
72private:
73    AwesomePlayer *mPlayer;
74    void (AwesomePlayer::*mMethod)();
75
76    AwesomeEvent(const AwesomeEvent &);
77    AwesomeEvent &operator=(const AwesomeEvent &);
78};
79
80struct AwesomeRemoteRenderer : public AwesomeRenderer {
81    AwesomeRemoteRenderer(const sp<IOMXRenderer> &target)
82        : mTarget(target) {
83    }
84
85    virtual void render(MediaBuffer *buffer) {
86        void *id;
87        if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) {
88            mTarget->render((IOMX::buffer_id)id);
89        }
90    }
91
92private:
93    sp<IOMXRenderer> mTarget;
94
95    AwesomeRemoteRenderer(const AwesomeRemoteRenderer &);
96    AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &);
97};
98
99struct AwesomeLocalRenderer : public AwesomeRenderer {
100    AwesomeLocalRenderer(
101            bool previewOnly,
102            const char *componentName,
103            OMX_COLOR_FORMATTYPE colorFormat,
104            const sp<ISurface> &isurface,
105            const sp<Surface> &surface,
106            size_t displayWidth, size_t displayHeight,
107            size_t decodedWidth, size_t decodedHeight)
108        : mTarget(NULL),
109          mLibHandle(NULL) {
110            init(previewOnly, componentName,
111                 colorFormat, isurface, surface, displayWidth,
112                 displayHeight, decodedWidth, decodedHeight);
113    }
114
115    virtual void render(MediaBuffer *buffer) {
116        render((const uint8_t *)buffer->data() + buffer->range_offset(),
117               buffer->range_length());
118    }
119
120    void render(const void *data, size_t size) {
121        mTarget->render(data, size, NULL);
122    }
123
124protected:
125    virtual ~AwesomeLocalRenderer() {
126        delete mTarget;
127        mTarget = NULL;
128
129        if (mLibHandle) {
130            dlclose(mLibHandle);
131            mLibHandle = NULL;
132        }
133    }
134
135private:
136    VideoRenderer *mTarget;
137    void *mLibHandle;
138
139    void init(
140            bool previewOnly,
141            const char *componentName,
142            OMX_COLOR_FORMATTYPE colorFormat,
143            const sp<ISurface> &isurface,
144            const sp<Surface> &surface,
145            size_t displayWidth, size_t displayHeight,
146            size_t decodedWidth, size_t decodedHeight);
147
148    AwesomeLocalRenderer(const AwesomeLocalRenderer &);
149    AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
150};
151
152void AwesomeLocalRenderer::init(
153        bool previewOnly,
154        const char *componentName,
155        OMX_COLOR_FORMATTYPE colorFormat,
156        const sp<ISurface> &isurface,
157        const sp<Surface> &surface,
158        size_t displayWidth, size_t displayHeight,
159        size_t decodedWidth, size_t decodedHeight) {
160    if (!previewOnly) {
161        // We will stick to the vanilla software-color-converting renderer
162        // for "previewOnly" mode, to avoid unneccessarily switching overlays
163        // more often than necessary.
164
165        mLibHandle = dlopen("libstagefrighthw.so", RTLD_NOW);
166
167        if (mLibHandle) {
168            typedef VideoRenderer *(*CreateRendererFunc)(
169                    const sp<ISurface> &surface,
170                    const char *componentName,
171                    OMX_COLOR_FORMATTYPE colorFormat,
172                    size_t displayWidth, size_t displayHeight,
173                    size_t decodedWidth, size_t decodedHeight);
174
175            CreateRendererFunc func =
176                (CreateRendererFunc)dlsym(
177                        mLibHandle,
178                        "_Z14createRendererRKN7android2spINS_8ISurfaceEEEPKc20"
179                        "OMX_COLOR_FORMATTYPEjjjj");
180
181            if (func) {
182                mTarget =
183                    (*func)(isurface, componentName, colorFormat,
184                        displayWidth, displayHeight,
185                        decodedWidth, decodedHeight);
186            }
187        }
188    }
189
190    if (mTarget == NULL) {
191        mTarget = new SoftwareRenderer(
192                colorFormat, surface, displayWidth, displayHeight,
193                decodedWidth, decodedHeight);
194    }
195}
196
197AwesomePlayer::AwesomePlayer()
198    : mQueueStarted(false),
199      mTimeSource(NULL),
200      mVideoRendererIsPreview(false),
201      mAudioPlayer(NULL),
202      mFlags(0),
203      mExtractorFlags(0),
204      mLastVideoBuffer(NULL),
205      mVideoBuffer(NULL),
206      mSuspensionState(NULL) {
207    CHECK_EQ(mClient.connect(), OK);
208
209    DataSource::RegisterDefaultSniffers();
210
211    mVideoEvent = new AwesomeEvent(this, &AwesomePlayer::onVideoEvent);
212    mVideoEventPending = false;
213    mStreamDoneEvent = new AwesomeEvent(this, &AwesomePlayer::onStreamDone);
214    mStreamDoneEventPending = false;
215    mBufferingEvent = new AwesomeEvent(this, &AwesomePlayer::onBufferingUpdate);
216    mBufferingEventPending = false;
217
218    mCheckAudioStatusEvent = new AwesomeEvent(
219            this, &AwesomePlayer::onCheckAudioStatus);
220
221    mAudioStatusEventPending = false;
222
223    reset();
224}
225
226AwesomePlayer::~AwesomePlayer() {
227    if (mQueueStarted) {
228        mQueue.stop();
229    }
230
231    reset();
232
233    mClient.disconnect();
234}
235
236void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
237    mQueue.cancelEvent(mVideoEvent->eventID());
238    mVideoEventPending = false;
239    mQueue.cancelEvent(mStreamDoneEvent->eventID());
240    mStreamDoneEventPending = false;
241    mQueue.cancelEvent(mCheckAudioStatusEvent->eventID());
242    mAudioStatusEventPending = false;
243
244    if (!keepBufferingGoing) {
245        mQueue.cancelEvent(mBufferingEvent->eventID());
246        mBufferingEventPending = false;
247    }
248}
249
250void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
251    Mutex::Autolock autoLock(mLock);
252    mListener = listener;
253}
254
255status_t AwesomePlayer::setDataSource(
256        const char *uri, const KeyedVector<String8, String8> *headers) {
257    Mutex::Autolock autoLock(mLock);
258    return setDataSource_l(uri, headers);
259}
260
261status_t AwesomePlayer::setDataSource_l(
262        const char *uri, const KeyedVector<String8, String8> *headers) {
263    reset_l();
264
265    mUri = uri;
266
267    if (headers) {
268        mUriHeaders = *headers;
269    }
270
271    // The actual work will be done during preparation in the call to
272    // ::finishSetDataSource_l to avoid blocking the calling thread in
273    // setDataSource for any significant time.
274
275    return OK;
276}
277
278status_t AwesomePlayer::setDataSource(
279        int fd, int64_t offset, int64_t length) {
280    Mutex::Autolock autoLock(mLock);
281
282    reset_l();
283
284    sp<DataSource> dataSource = new FileSource(fd, offset, length);
285
286    status_t err = dataSource->initCheck();
287
288    if (err != OK) {
289        return err;
290    }
291
292    mFileSource = dataSource;
293
294    return setDataSource_l(dataSource);
295}
296
297status_t AwesomePlayer::setDataSource_l(
298        const sp<DataSource> &dataSource) {
299    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
300
301    if (extractor == NULL) {
302        return UNKNOWN_ERROR;
303    }
304
305    return setDataSource_l(extractor);
306}
307
308status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
309    bool haveAudio = false;
310    bool haveVideo = false;
311    for (size_t i = 0; i < extractor->countTracks(); ++i) {
312        sp<MetaData> meta = extractor->getTrackMetaData(i);
313
314        const char *mime;
315        CHECK(meta->findCString(kKeyMIMEType, &mime));
316
317        if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
318            setVideoSource(extractor->getTrack(i));
319            haveVideo = true;
320        } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
321            setAudioSource(extractor->getTrack(i));
322            haveAudio = true;
323
324            if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
325                // Only do this for vorbis audio, none of the other audio
326                // formats even support this ringtone specific hack and
327                // retrieving the metadata on some extractors may turn out
328                // to be very expensive.
329                sp<MetaData> fileMeta = extractor->getMetaData();
330                int32_t loop;
331                if (fileMeta != NULL
332                        && fileMeta->findInt32(kKeyAutoLoop, &loop) && loop != 0) {
333                    mFlags |= AUTO_LOOPING;
334                }
335            }
336        }
337
338        if (haveAudio && haveVideo) {
339            break;
340        }
341    }
342
343    if (!haveAudio && !haveVideo) {
344        return UNKNOWN_ERROR;
345    }
346
347    mExtractorFlags = extractor->flags();
348
349    return OK;
350}
351
352void AwesomePlayer::reset() {
353    Mutex::Autolock autoLock(mLock);
354    reset_l();
355}
356
357void AwesomePlayer::reset_l() {
358    if (mFlags & PREPARING) {
359        mFlags |= PREPARE_CANCELLED;
360        if (mConnectingDataSource != NULL) {
361            LOGI("interrupting the connection process");
362            mConnectingDataSource->disconnect();
363        }
364    }
365
366    while (mFlags & PREPARING) {
367        mPreparedCondition.wait(mLock);
368    }
369
370    cancelPlayerEvents();
371
372    mCachedSource.clear();
373    mAudioTrack.clear();
374    mVideoTrack.clear();
375
376    // Shutdown audio first, so that the respone to the reset request
377    // appears to happen instantaneously as far as the user is concerned
378    // If we did this later, audio would continue playing while we
379    // shutdown the video-related resources and the player appear to
380    // not be as responsive to a reset request.
381    if (mAudioPlayer == NULL && mAudioSource != NULL) {
382        // If we had an audio player, it would have effectively
383        // taken possession of the audio source and stopped it when
384        // _it_ is stopped. Otherwise this is still our responsibility.
385        mAudioSource->stop();
386    }
387    mAudioSource.clear();
388
389    mTimeSource = NULL;
390
391    delete mAudioPlayer;
392    mAudioPlayer = NULL;
393
394    mVideoRenderer.clear();
395
396    if (mLastVideoBuffer) {
397        mLastVideoBuffer->release();
398        mLastVideoBuffer = NULL;
399    }
400
401    if (mVideoBuffer) {
402        mVideoBuffer->release();
403        mVideoBuffer = NULL;
404    }
405
406    if (mRTSPController != NULL) {
407        mRTSPController->disconnect();
408        mRTSPController.clear();
409    }
410
411    mRTPPusher.clear();
412    mRTCPPusher.clear();
413    mRTPSession.clear();
414
415    if (mVideoSource != NULL) {
416        mVideoSource->stop();
417
418        // The following hack is necessary to ensure that the OMX
419        // component is completely released by the time we may try
420        // to instantiate it again.
421        wp<MediaSource> tmp = mVideoSource;
422        mVideoSource.clear();
423        while (tmp.promote() != NULL) {
424            usleep(1000);
425        }
426        IPCThreadState::self()->flushCommands();
427    }
428
429    mDurationUs = -1;
430    mFlags = 0;
431    mExtractorFlags = 0;
432    mVideoWidth = mVideoHeight = -1;
433    mTimeSourceDeltaUs = 0;
434    mVideoTimeUs = 0;
435
436    mSeeking = false;
437    mSeekNotificationSent = false;
438    mSeekTimeUs = 0;
439
440    mUri.setTo("");
441    mUriHeaders.clear();
442
443    mFileSource.clear();
444
445    delete mSuspensionState;
446    mSuspensionState = NULL;
447}
448
449void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
450    if (mListener != NULL) {
451        sp<MediaPlayerBase> listener = mListener.promote();
452
453        if (listener != NULL) {
454            listener->sendEvent(msg, ext1, ext2);
455        }
456    }
457}
458
459// Returns true iff cached duration is available/applicable.
460bool AwesomePlayer::getCachedDuration_l(int64_t *durationUs, bool *eos) {
461    off_t totalSize;
462
463    if (mRTSPController != NULL) {
464        *durationUs = mRTSPController->getQueueDurationUs(eos);
465        return true;
466    } else if (mCachedSource != NULL && mDurationUs >= 0
467            && mCachedSource->getSize(&totalSize) == OK) {
468        int64_t bitrate = totalSize * 8000000ll / mDurationUs;  // in bits/sec
469
470        size_t cachedDataRemaining = mCachedSource->approxDataRemaining(eos);
471        *durationUs = cachedDataRemaining * 8000000ll / bitrate;
472        return true;
473    }
474
475    return false;
476}
477
478void AwesomePlayer::onBufferingUpdate() {
479    Mutex::Autolock autoLock(mLock);
480    if (!mBufferingEventPending) {
481        return;
482    }
483    mBufferingEventPending = false;
484
485    if (mCachedSource != NULL) {
486        bool eos;
487        size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&eos);
488
489        if (eos) {
490            notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
491            if (mFlags & PREPARING) {
492                LOGV("cache has reached EOS, prepare is done.");
493                finishAsyncPrepare_l();
494            }
495        } else {
496            off_t size;
497            if (mDurationUs >= 0 && mCachedSource->getSize(&size) == OK) {
498                int64_t bitrate = size * 8000000ll / mDurationUs;  // in bits/sec
499
500                size_t cachedSize = mCachedSource->cachedSize();
501                int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
502
503                int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
504                if (percentage > 100) {
505                    percentage = 100;
506                }
507
508                notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
509            } else {
510                // We don't know the bitrate of the stream, use absolute size
511                // limits to maintain the cache.
512
513                const size_t kLowWaterMarkBytes = 40000;
514                const size_t kHighWaterMarkBytes = 200000;
515
516                if ((mFlags & PLAYING) && !eos
517                        && (cachedDataRemaining < kLowWaterMarkBytes)) {
518                    LOGI("cache is running low (< %d) , pausing.",
519                         kLowWaterMarkBytes);
520                    mFlags |= CACHE_UNDERRUN;
521                    pause_l();
522                    notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
523                } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
524                    if (mFlags & CACHE_UNDERRUN) {
525                        LOGI("cache has filled up (> %d), resuming.",
526                             kHighWaterMarkBytes);
527                        mFlags &= ~CACHE_UNDERRUN;
528                        play_l();
529                        notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
530                    } else if (mFlags & PREPARING) {
531                        LOGV("cache has filled up (> %d), prepare is done",
532                             kHighWaterMarkBytes);
533                        finishAsyncPrepare_l();
534                    }
535                }
536            }
537        }
538    }
539
540    int64_t cachedDurationUs;
541    bool eos;
542    if (getCachedDuration_l(&cachedDurationUs, &eos)) {
543        if ((mFlags & PLAYING) && !eos
544                && (cachedDurationUs < kLowWaterMarkUs)) {
545            LOGI("cache is running low (%.2f secs) , pausing.",
546                 cachedDurationUs / 1E6);
547            mFlags |= CACHE_UNDERRUN;
548            pause_l();
549            notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
550        } else if (eos || cachedDurationUs > kHighWaterMarkUs) {
551            if (mFlags & CACHE_UNDERRUN) {
552                LOGI("cache has filled up (%.2f secs), resuming.",
553                     cachedDurationUs / 1E6);
554                mFlags &= ~CACHE_UNDERRUN;
555                play_l();
556                notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
557            } else if (mFlags & PREPARING) {
558                LOGV("cache has filled up (%.2f secs), prepare is done",
559                     cachedDurationUs / 1E6);
560                finishAsyncPrepare_l();
561            }
562        }
563    }
564
565    postBufferingEvent_l();
566}
567
568void AwesomePlayer::partial_reset_l() {
569    // Only reset the video renderer and shut down the video decoder.
570    // Then instantiate a new video decoder and resume video playback.
571
572    mVideoRenderer.clear();
573
574    if (mLastVideoBuffer) {
575        mLastVideoBuffer->release();
576        mLastVideoBuffer = NULL;
577    }
578
579    if (mVideoBuffer) {
580        mVideoBuffer->release();
581        mVideoBuffer = NULL;
582    }
583
584    {
585        mVideoSource->stop();
586
587        // The following hack is necessary to ensure that the OMX
588        // component is completely released by the time we may try
589        // to instantiate it again.
590        wp<MediaSource> tmp = mVideoSource;
591        mVideoSource.clear();
592        while (tmp.promote() != NULL) {
593            usleep(1000);
594        }
595        IPCThreadState::self()->flushCommands();
596    }
597
598    CHECK_EQ(OK, initVideoDecoder(OMXCodec::kIgnoreCodecSpecificData));
599}
600
601void AwesomePlayer::onStreamDone() {
602    // Posted whenever any stream finishes playing.
603
604    Mutex::Autolock autoLock(mLock);
605    if (!mStreamDoneEventPending) {
606        return;
607    }
608    mStreamDoneEventPending = false;
609
610    if (mStreamDoneStatus == INFO_DISCONTINUITY) {
611        // This special status is returned because an http live stream's
612        // video stream switched to a different bandwidth at this point
613        // and future data may have been encoded using different parameters.
614        // This requires us to shutdown the video decoder and reinstantiate
615        // a fresh one.
616
617        LOGV("INFO_DISCONTINUITY");
618
619        CHECK(mVideoSource != NULL);
620
621        partial_reset_l();
622        postVideoEvent_l();
623        return;
624    } else if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
625        LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
626
627        notifyListener_l(
628                MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
629
630        pause_l(true /* at eos */);
631
632        mFlags |= AT_EOS;
633        return;
634    }
635
636    const bool allDone =
637        (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
638            && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
639
640    if (!allDone) {
641        return;
642    }
643
644    if (mFlags & (LOOPING | AUTO_LOOPING)) {
645        seekTo_l(0);
646
647        if (mVideoSource != NULL) {
648            postVideoEvent_l();
649        }
650    } else {
651        LOGV("MEDIA_PLAYBACK_COMPLETE");
652        notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
653
654        pause_l(true /* at eos */);
655
656        mFlags |= AT_EOS;
657    }
658}
659
660status_t AwesomePlayer::play() {
661    Mutex::Autolock autoLock(mLock);
662
663    mFlags &= ~CACHE_UNDERRUN;
664
665    return play_l();
666}
667
668status_t AwesomePlayer::play_l() {
669    if (mFlags & PLAYING) {
670        return OK;
671    }
672
673    if (!(mFlags & PREPARED)) {
674        status_t err = prepare_l();
675
676        if (err != OK) {
677            return err;
678        }
679    }
680
681    mFlags |= PLAYING;
682    mFlags |= FIRST_FRAME;
683
684    bool deferredAudioSeek = false;
685
686    if (mAudioSource != NULL) {
687        if (mAudioPlayer == NULL) {
688            if (mAudioSink != NULL) {
689                mAudioPlayer = new AudioPlayer(mAudioSink, this);
690                mAudioPlayer->setSource(mAudioSource);
691
692                // We've already started the MediaSource in order to enable
693                // the prefetcher to read its data.
694                status_t err = mAudioPlayer->start(
695                        true /* sourceAlreadyStarted */);
696
697                if (err != OK) {
698                    delete mAudioPlayer;
699                    mAudioPlayer = NULL;
700
701                    mFlags &= ~(PLAYING | FIRST_FRAME);
702
703                    return err;
704                }
705
706                mTimeSource = mAudioPlayer;
707
708                deferredAudioSeek = true;
709
710                mWatchForAudioSeekComplete = false;
711                mWatchForAudioEOS = true;
712            }
713        } else {
714            mAudioPlayer->resume();
715        }
716    }
717
718    if (mTimeSource == NULL && mAudioPlayer == NULL) {
719        mTimeSource = &mSystemTimeSource;
720    }
721
722    if (mVideoSource != NULL) {
723        // Kick off video playback
724        postVideoEvent_l();
725    }
726
727    if (deferredAudioSeek) {
728        // If there was a seek request while we were paused
729        // and we're just starting up again, honor the request now.
730        seekAudioIfNecessary_l();
731    }
732
733    if (mFlags & AT_EOS) {
734        // Legacy behaviour, if a stream finishes playing and then
735        // is started again, we play from the start...
736        seekTo_l(0);
737    }
738
739    return OK;
740}
741
742void AwesomePlayer::notifyVideoSize_l() {
743    sp<MetaData> meta = mVideoSource->getFormat();
744
745    int32_t decodedWidth, decodedHeight;
746    CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
747    CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
748
749    notifyListener_l(MEDIA_SET_VIDEO_SIZE, decodedWidth, decodedHeight);
750}
751
752void AwesomePlayer::initRenderer_l() {
753    if (mSurface != NULL || mISurface != NULL) {
754        sp<MetaData> meta = mVideoSource->getFormat();
755
756        int32_t format;
757        const char *component;
758        int32_t decodedWidth, decodedHeight;
759        CHECK(meta->findInt32(kKeyColorFormat, &format));
760        CHECK(meta->findCString(kKeyDecoderComponent, &component));
761        CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
762        CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
763
764        mVideoRenderer.clear();
765
766        // Must ensure that mVideoRenderer's destructor is actually executed
767        // before creating a new one.
768        IPCThreadState::self()->flushCommands();
769
770        if (mSurface != NULL) {
771            // Other decoders are instantiated locally and as a consequence
772            // allocate their buffers in local address space.
773            mVideoRenderer = new AwesomeLocalRenderer(
774                false,  // previewOnly
775                component,
776                (OMX_COLOR_FORMATTYPE)format,
777                mISurface,
778                mSurface,
779                mVideoWidth, mVideoHeight,
780                decodedWidth, decodedHeight);
781        } else {
782            // Our OMX codecs allocate buffers on the media_server side
783            // therefore they require a remote IOMXRenderer that knows how
784            // to display them.
785            mVideoRenderer = new AwesomeRemoteRenderer(
786                mClient.interface()->createRenderer(
787                        mISurface, component,
788                        (OMX_COLOR_FORMATTYPE)format,
789                        decodedWidth, decodedHeight,
790                        mVideoWidth, mVideoHeight));
791        }
792    }
793}
794
795status_t AwesomePlayer::pause() {
796    Mutex::Autolock autoLock(mLock);
797
798    mFlags &= ~CACHE_UNDERRUN;
799
800    return pause_l();
801}
802
803status_t AwesomePlayer::pause_l(bool at_eos) {
804    if (!(mFlags & PLAYING)) {
805        return OK;
806    }
807
808    cancelPlayerEvents(true /* keepBufferingGoing */);
809
810    if (mAudioPlayer != NULL) {
811        if (at_eos) {
812            // If we played the audio stream to completion we
813            // want to make sure that all samples remaining in the audio
814            // track's queue are played out.
815            mAudioPlayer->pause(true /* playPendingSamples */);
816        } else {
817            mAudioPlayer->pause();
818        }
819    }
820
821    mFlags &= ~PLAYING;
822
823    return OK;
824}
825
826bool AwesomePlayer::isPlaying() const {
827    return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
828}
829
830void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
831    Mutex::Autolock autoLock(mLock);
832
833    mISurface = isurface;
834}
835
836void AwesomePlayer::setSurface(const sp<Surface> &surface) {
837    Mutex::Autolock autoLock(mLock);
838
839    mSurface = surface;
840}
841
842void AwesomePlayer::setAudioSink(
843        const sp<MediaPlayerBase::AudioSink> &audioSink) {
844    Mutex::Autolock autoLock(mLock);
845
846    mAudioSink = audioSink;
847}
848
849status_t AwesomePlayer::setLooping(bool shouldLoop) {
850    Mutex::Autolock autoLock(mLock);
851
852    mFlags = mFlags & ~LOOPING;
853
854    if (shouldLoop) {
855        mFlags |= LOOPING;
856    }
857
858    return OK;
859}
860
861status_t AwesomePlayer::getDuration(int64_t *durationUs) {
862    Mutex::Autolock autoLock(mMiscStateLock);
863
864    if (mDurationUs < 0) {
865        return UNKNOWN_ERROR;
866    }
867
868    *durationUs = mDurationUs;
869
870    return OK;
871}
872
873status_t AwesomePlayer::getPosition(int64_t *positionUs) {
874    if (mRTSPController != NULL) {
875        *positionUs = mRTSPController->getNormalPlayTimeUs();
876    }
877    else if (mSeeking) {
878        *positionUs = mSeekTimeUs;
879    } else if (mVideoSource != NULL) {
880        Mutex::Autolock autoLock(mMiscStateLock);
881        *positionUs = mVideoTimeUs;
882    } else if (mAudioPlayer != NULL) {
883        *positionUs = mAudioPlayer->getMediaTimeUs();
884    } else {
885        *positionUs = 0;
886    }
887
888    return OK;
889}
890
891status_t AwesomePlayer::seekTo(int64_t timeUs) {
892    if (mExtractorFlags & MediaExtractor::CAN_SEEK) {
893        Mutex::Autolock autoLock(mLock);
894        return seekTo_l(timeUs);
895    }
896
897    return OK;
898}
899
900// static
901void AwesomePlayer::OnRTSPSeekDoneWrapper(void *cookie) {
902    static_cast<AwesomePlayer *>(cookie)->onRTSPSeekDone();
903}
904
905void AwesomePlayer::onRTSPSeekDone() {
906    notifyListener_l(MEDIA_SEEK_COMPLETE);
907    mSeekNotificationSent = true;
908}
909
910status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
911    if (mRTSPController != NULL) {
912        mRTSPController->seekAsync(timeUs, OnRTSPSeekDoneWrapper, this);
913        return OK;
914    }
915
916    if (mFlags & CACHE_UNDERRUN) {
917        mFlags &= ~CACHE_UNDERRUN;
918        play_l();
919    }
920
921    mSeeking = true;
922    mSeekNotificationSent = false;
923    mSeekTimeUs = timeUs;
924    mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
925
926    seekAudioIfNecessary_l();
927
928    if (!(mFlags & PLAYING)) {
929        LOGV("seeking while paused, sending SEEK_COMPLETE notification"
930             " immediately.");
931
932        notifyListener_l(MEDIA_SEEK_COMPLETE);
933        mSeekNotificationSent = true;
934    }
935
936    return OK;
937}
938
939void AwesomePlayer::seekAudioIfNecessary_l() {
940    if (mSeeking && mVideoSource == NULL && mAudioPlayer != NULL) {
941        mAudioPlayer->seekTo(mSeekTimeUs);
942
943        mWatchForAudioSeekComplete = true;
944        mWatchForAudioEOS = true;
945        mSeekNotificationSent = false;
946    }
947}
948
949status_t AwesomePlayer::getVideoDimensions(
950        int32_t *width, int32_t *height) const {
951    Mutex::Autolock autoLock(mLock);
952
953    if (mVideoWidth < 0 || mVideoHeight < 0) {
954        return UNKNOWN_ERROR;
955    }
956
957    *width = mVideoWidth;
958    *height = mVideoHeight;
959
960    return OK;
961}
962
963void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
964    CHECK(source != NULL);
965
966    mAudioTrack = source;
967}
968
969status_t AwesomePlayer::initAudioDecoder() {
970    sp<MetaData> meta = mAudioTrack->getFormat();
971
972    const char *mime;
973    CHECK(meta->findCString(kKeyMIMEType, &mime));
974
975    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
976        mAudioSource = mAudioTrack;
977    } else {
978        mAudioSource = OMXCodec::Create(
979                mClient.interface(), mAudioTrack->getFormat(),
980                false, // createEncoder
981                mAudioTrack);
982    }
983
984    if (mAudioSource != NULL) {
985        int64_t durationUs;
986        if (mAudioTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
987            Mutex::Autolock autoLock(mMiscStateLock);
988            if (mDurationUs < 0 || durationUs > mDurationUs) {
989                mDurationUs = durationUs;
990            }
991        }
992
993        status_t err = mAudioSource->start();
994
995        if (err != OK) {
996            mAudioSource.clear();
997            return err;
998        }
999    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_QCELP)) {
1000        // For legacy reasons we're simply going to ignore the absence
1001        // of an audio decoder for QCELP instead of aborting playback
1002        // altogether.
1003        return OK;
1004    }
1005
1006    return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
1007}
1008
1009void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
1010    CHECK(source != NULL);
1011
1012    mVideoTrack = source;
1013}
1014
1015status_t AwesomePlayer::initVideoDecoder(uint32_t flags) {
1016    mVideoSource = OMXCodec::Create(
1017            mClient.interface(), mVideoTrack->getFormat(),
1018            false, // createEncoder
1019            mVideoTrack,
1020            NULL, flags);
1021
1022    if (mVideoSource != NULL) {
1023        int64_t durationUs;
1024        if (mVideoTrack->getFormat()->findInt64(kKeyDuration, &durationUs)) {
1025            Mutex::Autolock autoLock(mMiscStateLock);
1026            if (mDurationUs < 0 || durationUs > mDurationUs) {
1027                mDurationUs = durationUs;
1028            }
1029        }
1030
1031        CHECK(mVideoTrack->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
1032        CHECK(mVideoTrack->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
1033
1034        status_t err = mVideoSource->start();
1035
1036        if (err != OK) {
1037            mVideoSource.clear();
1038            return err;
1039        }
1040    }
1041
1042    return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
1043}
1044
1045void AwesomePlayer::onVideoEvent() {
1046    Mutex::Autolock autoLock(mLock);
1047    if (!mVideoEventPending) {
1048        // The event has been cancelled in reset_l() but had already
1049        // been scheduled for execution at that time.
1050        return;
1051    }
1052    mVideoEventPending = false;
1053
1054    if (mSeeking) {
1055        if (mLastVideoBuffer) {
1056            mLastVideoBuffer->release();
1057            mLastVideoBuffer = NULL;
1058        }
1059
1060        if (mVideoBuffer) {
1061            mVideoBuffer->release();
1062            mVideoBuffer = NULL;
1063        }
1064
1065        if (mCachedSource != NULL && mAudioSource != NULL) {
1066            // We're going to seek the video source first, followed by
1067            // the audio source.
1068            // In order to avoid jumps in the DataSource offset caused by
1069            // the audio codec prefetching data from the old locations
1070            // while the video codec is already reading data from the new
1071            // locations, we'll "pause" the audio source, causing it to
1072            // stop reading input data until a subsequent seek.
1073
1074            if (mAudioPlayer != NULL) {
1075                mAudioPlayer->pause();
1076            }
1077            mAudioSource->pause();
1078        }
1079    }
1080
1081    if (!mVideoBuffer) {
1082        MediaSource::ReadOptions options;
1083        if (mSeeking) {
1084            LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
1085
1086            options.setSeekTo(
1087                    mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
1088        }
1089        for (;;) {
1090            status_t err = mVideoSource->read(&mVideoBuffer, &options);
1091            options.clearSeekTo();
1092
1093            if (err != OK) {
1094                CHECK_EQ(mVideoBuffer, NULL);
1095
1096                if (err == INFO_FORMAT_CHANGED) {
1097                    LOGV("VideoSource signalled format change.");
1098
1099                    notifyVideoSize_l();
1100
1101                    if (mVideoRenderer != NULL) {
1102                        mVideoRendererIsPreview = false;
1103                        initRenderer_l();
1104                    }
1105                    continue;
1106                }
1107
1108                mFlags |= VIDEO_AT_EOS;
1109                postStreamDoneEvent_l(err);
1110                return;
1111            }
1112
1113            if (mVideoBuffer->range_length() == 0) {
1114                // Some decoders, notably the PV AVC software decoder
1115                // return spurious empty buffers that we just want to ignore.
1116
1117                mVideoBuffer->release();
1118                mVideoBuffer = NULL;
1119                continue;
1120            }
1121
1122            break;
1123        }
1124    }
1125
1126    int64_t timeUs;
1127    CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
1128
1129    {
1130        Mutex::Autolock autoLock(mMiscStateLock);
1131        mVideoTimeUs = timeUs;
1132    }
1133
1134    if (mSeeking) {
1135        if (mAudioPlayer != NULL) {
1136            LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
1137
1138            mAudioPlayer->seekTo(timeUs);
1139            mAudioPlayer->resume();
1140            mWatchForAudioSeekComplete = true;
1141            mWatchForAudioEOS = true;
1142        } else if (!mSeekNotificationSent) {
1143            // If we're playing video only, report seek complete now,
1144            // otherwise audio player will notify us later.
1145            notifyListener_l(MEDIA_SEEK_COMPLETE);
1146        }
1147
1148        mFlags |= FIRST_FRAME;
1149        mSeeking = false;
1150        mSeekNotificationSent = false;
1151    }
1152
1153    TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
1154
1155    if (mFlags & FIRST_FRAME) {
1156        mFlags &= ~FIRST_FRAME;
1157
1158        mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
1159    }
1160
1161    int64_t realTimeUs, mediaTimeUs;
1162    if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
1163        && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
1164        mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
1165    }
1166
1167    int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
1168
1169    int64_t latenessUs = nowUs - timeUs;
1170
1171    if (mRTPSession != NULL) {
1172        // We'll completely ignore timestamps for gtalk videochat
1173        // and we'll play incoming video as fast as we get it.
1174        latenessUs = 0;
1175    }
1176
1177    if (latenessUs > 40000) {
1178        // We're more than 40ms late.
1179        LOGV("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
1180
1181        mVideoBuffer->release();
1182        mVideoBuffer = NULL;
1183
1184        postVideoEvent_l();
1185        return;
1186    }
1187
1188    if (latenessUs < -10000) {
1189        // We're more than 10ms early.
1190
1191        postVideoEvent_l(10000);
1192        return;
1193    }
1194
1195    if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
1196        mVideoRendererIsPreview = false;
1197
1198        initRenderer_l();
1199    }
1200
1201    if (mVideoRenderer != NULL) {
1202        mVideoRenderer->render(mVideoBuffer);
1203    }
1204
1205    if (mLastVideoBuffer) {
1206        mLastVideoBuffer->release();
1207        mLastVideoBuffer = NULL;
1208    }
1209    mLastVideoBuffer = mVideoBuffer;
1210    mVideoBuffer = NULL;
1211
1212    postVideoEvent_l();
1213}
1214
1215void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
1216    if (mVideoEventPending) {
1217        return;
1218    }
1219
1220    mVideoEventPending = true;
1221    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
1222}
1223
1224void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
1225    if (mStreamDoneEventPending) {
1226        return;
1227    }
1228    mStreamDoneEventPending = true;
1229
1230    mStreamDoneStatus = status;
1231    mQueue.postEvent(mStreamDoneEvent);
1232}
1233
1234void AwesomePlayer::postBufferingEvent_l() {
1235    if (mBufferingEventPending) {
1236        return;
1237    }
1238    mBufferingEventPending = true;
1239    mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
1240}
1241
1242void AwesomePlayer::postCheckAudioStatusEvent_l() {
1243    if (mAudioStatusEventPending) {
1244        return;
1245    }
1246    mAudioStatusEventPending = true;
1247    mQueue.postEvent(mCheckAudioStatusEvent);
1248}
1249
1250void AwesomePlayer::onCheckAudioStatus() {
1251    Mutex::Autolock autoLock(mLock);
1252    if (!mAudioStatusEventPending) {
1253        // Event was dispatched and while we were blocking on the mutex,
1254        // has already been cancelled.
1255        return;
1256    }
1257
1258    mAudioStatusEventPending = false;
1259
1260    if (mWatchForAudioSeekComplete && !mAudioPlayer->isSeeking()) {
1261        mWatchForAudioSeekComplete = false;
1262
1263        if (!mSeekNotificationSent) {
1264            notifyListener_l(MEDIA_SEEK_COMPLETE);
1265            mSeekNotificationSent = true;
1266        }
1267
1268        mSeeking = false;
1269    }
1270
1271    status_t finalStatus;
1272    if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
1273        mWatchForAudioEOS = false;
1274        mFlags |= AUDIO_AT_EOS;
1275        mFlags |= FIRST_FRAME;
1276        postStreamDoneEvent_l(finalStatus);
1277    }
1278}
1279
1280status_t AwesomePlayer::prepare() {
1281    Mutex::Autolock autoLock(mLock);
1282    return prepare_l();
1283}
1284
1285status_t AwesomePlayer::prepare_l() {
1286    if (mFlags & PREPARED) {
1287        return OK;
1288    }
1289
1290    if (mFlags & PREPARING) {
1291        return UNKNOWN_ERROR;
1292    }
1293
1294    mIsAsyncPrepare = false;
1295    status_t err = prepareAsync_l();
1296
1297    if (err != OK) {
1298        return err;
1299    }
1300
1301    while (mFlags & PREPARING) {
1302        mPreparedCondition.wait(mLock);
1303    }
1304
1305    return mPrepareResult;
1306}
1307
1308status_t AwesomePlayer::prepareAsync() {
1309    Mutex::Autolock autoLock(mLock);
1310
1311    if (mFlags & PREPARING) {
1312        return UNKNOWN_ERROR;  // async prepare already pending
1313    }
1314
1315    mIsAsyncPrepare = true;
1316    return prepareAsync_l();
1317}
1318
1319status_t AwesomePlayer::prepareAsync_l() {
1320    if (mFlags & PREPARING) {
1321        return UNKNOWN_ERROR;  // async prepare already pending
1322    }
1323
1324    if (!mQueueStarted) {
1325        mQueue.start();
1326        mQueueStarted = true;
1327    }
1328
1329    mFlags |= PREPARING;
1330    mAsyncPrepareEvent = new AwesomeEvent(
1331            this, &AwesomePlayer::onPrepareAsyncEvent);
1332
1333    mQueue.postEvent(mAsyncPrepareEvent);
1334
1335    return OK;
1336}
1337
1338status_t AwesomePlayer::finishSetDataSource_l() {
1339    sp<DataSource> dataSource;
1340
1341    if (!strncasecmp("http://", mUri.string(), 7)) {
1342        mConnectingDataSource = new NuHTTPDataSource;
1343
1344        mLock.unlock();
1345        status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
1346        mLock.lock();
1347
1348        if (err != OK) {
1349            mConnectingDataSource.clear();
1350
1351            LOGI("mConnectingDataSource->connect() returned %d", err);
1352            return err;
1353        }
1354
1355#if 0
1356        mCachedSource = new NuCachedSource2(
1357                new ThrottledSource(
1358                    mConnectingDataSource, 50 * 1024 /* bytes/sec */));
1359#else
1360        mCachedSource = new NuCachedSource2(mConnectingDataSource);
1361#endif
1362        mConnectingDataSource.clear();
1363
1364        dataSource = mCachedSource;
1365    } else if (!strncasecmp(mUri.string(), "httplive://", 11)) {
1366        String8 uri("http://");
1367        uri.append(mUri.string() + 11);
1368
1369        sp<LiveSource> liveSource = new LiveSource(uri.string());
1370
1371        mCachedSource = new NuCachedSource2(liveSource);
1372        dataSource = mCachedSource;
1373
1374        sp<MediaExtractor> extractor =
1375            MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
1376
1377        static_cast<MPEG2TSExtractor *>(extractor.get())
1378            ->setLiveSource(liveSource);
1379
1380        return setDataSource_l(extractor);
1381    } else if (!strncmp("rtsp://gtalk/", mUri.string(), 13)) {
1382        if (mLooper == NULL) {
1383            mLooper = new ALooper;
1384            mLooper->setName("gtalk rtp");
1385            mLooper->start(
1386                    false /* runOnCallingThread */,
1387                    false /* canCallJava */,
1388                    PRIORITY_HIGHEST);
1389        }
1390
1391        const char *startOfCodecString = &mUri.string()[13];
1392        const char *startOfSlash1 = strchr(startOfCodecString, '/');
1393        if (startOfSlash1 == NULL) {
1394            return BAD_VALUE;
1395        }
1396        const char *startOfWidthString = &startOfSlash1[1];
1397        const char *startOfSlash2 = strchr(startOfWidthString, '/');
1398        if (startOfSlash2 == NULL) {
1399            return BAD_VALUE;
1400        }
1401        const char *startOfHeightString = &startOfSlash2[1];
1402
1403        String8 codecString(startOfCodecString, startOfSlash1 - startOfCodecString);
1404        String8 widthString(startOfWidthString, startOfSlash2 - startOfWidthString);
1405        String8 heightString(startOfHeightString);
1406
1407#if 0
1408        mRTPPusher = new UDPPusher("/data/misc/rtpout.bin", 5434);
1409        mLooper->registerHandler(mRTPPusher);
1410
1411        mRTCPPusher = new UDPPusher("/data/misc/rtcpout.bin", 5435);
1412        mLooper->registerHandler(mRTCPPusher);
1413#endif
1414
1415        mRTPSession = new ARTPSession;
1416        mLooper->registerHandler(mRTPSession);
1417
1418#if 0
1419        // My AMR SDP
1420        static const char *raw =
1421            "v=0\r\n"
1422            "o=- 64 233572944 IN IP4 127.0.0.0\r\n"
1423            "s=QuickTime\r\n"
1424            "t=0 0\r\n"
1425            "a=range:npt=0-315\r\n"
1426            "a=isma-compliance:2,2.0,2\r\n"
1427            "m=audio 5434 RTP/AVP 97\r\n"
1428            "c=IN IP4 127.0.0.1\r\n"
1429            "b=AS:30\r\n"
1430            "a=rtpmap:97 AMR/8000/1\r\n"
1431            "a=fmtp:97 octet-align\r\n";
1432#elif 1
1433        String8 sdp;
1434        sdp.appendFormat(
1435            "v=0\r\n"
1436            "o=- 64 233572944 IN IP4 127.0.0.0\r\n"
1437            "s=QuickTime\r\n"
1438            "t=0 0\r\n"
1439            "a=range:npt=0-315\r\n"
1440            "a=isma-compliance:2,2.0,2\r\n"
1441            "m=video 5434 RTP/AVP 97\r\n"
1442            "c=IN IP4 127.0.0.1\r\n"
1443            "b=AS:30\r\n"
1444            "a=rtpmap:97 %s/90000\r\n"
1445            "a=cliprect:0,0,%s,%s\r\n"
1446            "a=framesize:97 %s-%s\r\n",
1447
1448            codecString.string(),
1449            heightString.string(), widthString.string(),
1450            widthString.string(), heightString.string()
1451            );
1452        const char *raw = sdp.string();
1453
1454#endif
1455
1456        sp<ASessionDescription> desc = new ASessionDescription;
1457        CHECK(desc->setTo(raw, strlen(raw)));
1458
1459        CHECK_EQ(mRTPSession->setup(desc), (status_t)OK);
1460
1461        if (mRTPPusher != NULL) {
1462            mRTPPusher->start();
1463        }
1464
1465        if (mRTCPPusher != NULL) {
1466            mRTCPPusher->start();
1467        }
1468
1469        CHECK_EQ(mRTPSession->countTracks(), 1u);
1470        sp<MediaSource> source = mRTPSession->trackAt(0);
1471
1472#if 0
1473        bool eos;
1474        while (((APacketSource *)source.get())
1475                ->getQueuedDuration(&eos) < 5000000ll && !eos) {
1476            usleep(100000ll);
1477        }
1478#endif
1479
1480        const char *mime;
1481        CHECK(source->getFormat()->findCString(kKeyMIMEType, &mime));
1482
1483        if (!strncasecmp("video/", mime, 6)) {
1484            setVideoSource(source);
1485        } else {
1486            CHECK(!strncasecmp("audio/", mime, 6));
1487            setAudioSource(source);
1488        }
1489
1490        mExtractorFlags = MediaExtractor::CAN_PAUSE;
1491
1492        return OK;
1493    } else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
1494        if (mLooper == NULL) {
1495            mLooper = new ALooper;
1496            mLooper->setName("rtsp");
1497            mLooper->start();
1498        }
1499        mRTSPController = new ARTSPController(mLooper);
1500        status_t err = mRTSPController->connect(mUri.string());
1501
1502        LOGI("ARTSPController::connect returned %d", err);
1503
1504        if (err != OK) {
1505            mRTSPController.clear();
1506            return err;
1507        }
1508
1509        sp<MediaExtractor> extractor = mRTSPController.get();
1510        return setDataSource_l(extractor);
1511    } else {
1512        dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
1513    }
1514
1515    if (dataSource == NULL) {
1516        return UNKNOWN_ERROR;
1517    }
1518
1519    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
1520
1521    if (extractor == NULL) {
1522        return UNKNOWN_ERROR;
1523    }
1524
1525    return setDataSource_l(extractor);
1526}
1527
1528void AwesomePlayer::abortPrepare(status_t err) {
1529    CHECK(err != OK);
1530
1531    if (mIsAsyncPrepare) {
1532        notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1533    }
1534
1535    mPrepareResult = err;
1536    mFlags &= ~(PREPARING|PREPARE_CANCELLED);
1537    mAsyncPrepareEvent = NULL;
1538    mPreparedCondition.broadcast();
1539}
1540
1541// static
1542bool AwesomePlayer::ContinuePreparation(void *cookie) {
1543    AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
1544
1545    return (me->mFlags & PREPARE_CANCELLED) == 0;
1546}
1547
1548void AwesomePlayer::onPrepareAsyncEvent() {
1549    Mutex::Autolock autoLock(mLock);
1550
1551    if (mFlags & PREPARE_CANCELLED) {
1552        LOGI("prepare was cancelled before doing anything");
1553        abortPrepare(UNKNOWN_ERROR);
1554        return;
1555    }
1556
1557    if (mUri.size() > 0) {
1558        status_t err = finishSetDataSource_l();
1559
1560        if (err != OK) {
1561            abortPrepare(err);
1562            return;
1563        }
1564    }
1565
1566    if (mVideoTrack != NULL && mVideoSource == NULL) {
1567        status_t err = initVideoDecoder();
1568
1569        if (err != OK) {
1570            abortPrepare(err);
1571            return;
1572        }
1573    }
1574
1575    if (mAudioTrack != NULL && mAudioSource == NULL) {
1576        status_t err = initAudioDecoder();
1577
1578        if (err != OK) {
1579            abortPrepare(err);
1580            return;
1581        }
1582    }
1583
1584    if (mCachedSource != NULL || mRTSPController != NULL) {
1585        postBufferingEvent_l();
1586    } else {
1587        finishAsyncPrepare_l();
1588    }
1589}
1590
1591void AwesomePlayer::finishAsyncPrepare_l() {
1592    if (mIsAsyncPrepare) {
1593        if (mVideoSource == NULL) {
1594            notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
1595        } else {
1596            notifyVideoSize_l();
1597        }
1598
1599        notifyListener_l(MEDIA_PREPARED);
1600    }
1601
1602    mPrepareResult = OK;
1603    mFlags &= ~(PREPARING|PREPARE_CANCELLED);
1604    mFlags |= PREPARED;
1605    mAsyncPrepareEvent = NULL;
1606    mPreparedCondition.broadcast();
1607}
1608
1609status_t AwesomePlayer::suspend() {
1610    LOGV("suspend");
1611    Mutex::Autolock autoLock(mLock);
1612
1613    if (mSuspensionState != NULL) {
1614        if (mLastVideoBuffer == NULL) {
1615            //go into here if video is suspended again
1616            //after resuming without being played between
1617            //them
1618            SuspensionState *state = mSuspensionState;
1619            mSuspensionState = NULL;
1620            reset_l();
1621            mSuspensionState = state;
1622            return OK;
1623        }
1624
1625        delete mSuspensionState;
1626        mSuspensionState = NULL;
1627    }
1628
1629    if (mFlags & PREPARING) {
1630        mFlags |= PREPARE_CANCELLED;
1631        if (mConnectingDataSource != NULL) {
1632            LOGI("interrupting the connection process");
1633            mConnectingDataSource->disconnect();
1634        }
1635    }
1636
1637    while (mFlags & PREPARING) {
1638        mPreparedCondition.wait(mLock);
1639    }
1640
1641    SuspensionState *state = new SuspensionState;
1642    state->mUri = mUri;
1643    state->mUriHeaders = mUriHeaders;
1644    state->mFileSource = mFileSource;
1645
1646    state->mFlags = mFlags & (PLAYING | AUTO_LOOPING | LOOPING | AT_EOS);
1647    getPosition(&state->mPositionUs);
1648
1649    if (mLastVideoBuffer) {
1650        size_t size = mLastVideoBuffer->range_length();
1651
1652        if (size) {
1653            int32_t unreadable;
1654            if (!mLastVideoBuffer->meta_data()->findInt32(
1655                        kKeyIsUnreadable, &unreadable)
1656                    || unreadable == 0) {
1657                state->mLastVideoFrameSize = size;
1658                state->mLastVideoFrame = malloc(size);
1659                memcpy(state->mLastVideoFrame,
1660                       (const uint8_t *)mLastVideoBuffer->data()
1661                            + mLastVideoBuffer->range_offset(),
1662                       size);
1663
1664                state->mVideoWidth = mVideoWidth;
1665                state->mVideoHeight = mVideoHeight;
1666
1667                sp<MetaData> meta = mVideoSource->getFormat();
1668                CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat));
1669                CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth));
1670                CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight));
1671            } else {
1672                LOGV("Unable to save last video frame, we have no access to "
1673                     "the decoded video data.");
1674            }
1675        }
1676    }
1677
1678    reset_l();
1679
1680    mSuspensionState = state;
1681
1682    return OK;
1683}
1684
1685status_t AwesomePlayer::resume() {
1686    LOGV("resume");
1687    Mutex::Autolock autoLock(mLock);
1688
1689    if (mSuspensionState == NULL) {
1690        return INVALID_OPERATION;
1691    }
1692
1693    SuspensionState *state = mSuspensionState;
1694    mSuspensionState = NULL;
1695
1696    status_t err;
1697    if (state->mFileSource != NULL) {
1698        err = setDataSource_l(state->mFileSource);
1699
1700        if (err == OK) {
1701            mFileSource = state->mFileSource;
1702        }
1703    } else {
1704        err = setDataSource_l(state->mUri, &state->mUriHeaders);
1705    }
1706
1707    if (err != OK) {
1708        delete state;
1709        state = NULL;
1710
1711        return err;
1712    }
1713
1714    seekTo_l(state->mPositionUs);
1715
1716    mFlags = state->mFlags & (AUTO_LOOPING | LOOPING | AT_EOS);
1717
1718    if (state->mLastVideoFrame && (mSurface != NULL || mISurface != NULL)) {
1719        mVideoRenderer =
1720            new AwesomeLocalRenderer(
1721                    true,  // previewOnly
1722                    "",
1723                    (OMX_COLOR_FORMATTYPE)state->mColorFormat,
1724                    mISurface,
1725                    mSurface,
1726                    state->mVideoWidth,
1727                    state->mVideoHeight,
1728                    state->mDecodedWidth,
1729                    state->mDecodedHeight);
1730
1731        mVideoRendererIsPreview = true;
1732
1733        ((AwesomeLocalRenderer *)mVideoRenderer.get())->render(
1734                state->mLastVideoFrame, state->mLastVideoFrameSize);
1735    }
1736
1737    if (state->mFlags & PLAYING) {
1738        play_l();
1739    }
1740
1741    mSuspensionState = state;
1742    state = NULL;
1743
1744    return OK;
1745}
1746
1747uint32_t AwesomePlayer::flags() const {
1748    return mExtractorFlags;
1749}
1750
1751void AwesomePlayer::postAudioEOS() {
1752    postCheckAudioStatusEvent_l();
1753}
1754
1755void AwesomePlayer::postAudioSeekComplete() {
1756    postCheckAudioStatusEvent_l();
1757}
1758
1759}  // namespace android
1760
1761