AwesomePlayer.cpp revision 88c030e0e0152791ff74f90249f55fce01371198
1/*
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
21#include "include/AwesomePlayer.h"
22#include "include/Prefetcher.h"
23#include "include/SoftwareRenderer.h"
24
25#include <binder/IPCThreadState.h>
26#include <media/stagefright/AudioPlayer.h>
27#include <media/stagefright/DataSource.h>
28#include <media/stagefright/FileSource.h>
29#include <media/stagefright/MediaBuffer.h>
30#include <media/stagefright/MediaDefs.h>
31#include <media/stagefright/MediaExtractor.h>
32#include <media/stagefright/MediaDebug.h>
33#include <media/stagefright/MediaSource.h>
34#include <media/stagefright/MetaData.h>
35#include <media/stagefright/OMXCodec.h>
36
37namespace android {
38
39struct AwesomeEvent : public TimedEventQueue::Event {
40    AwesomeEvent(AwesomePlayer *player, int32_t code)
41        : mPlayer(player),
42          mCode(code) {
43    }
44
45protected:
46    virtual ~AwesomeEvent() {}
47
48    virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
49        mPlayer->onEvent(mCode);
50    }
51
52private:
53    AwesomePlayer *mPlayer;
54    int32_t mCode;
55
56    AwesomeEvent(const AwesomeEvent &);
57    AwesomeEvent &operator=(const AwesomeEvent &);
58};
59
60struct AwesomeRemoteRenderer : public AwesomeRenderer {
61    AwesomeRemoteRenderer(const sp<IOMXRenderer> &target)
62        : mTarget(target) {
63    }
64
65    virtual void render(MediaBuffer *buffer) {
66        void *id;
67        if (buffer->meta_data()->findPointer(kKeyBufferID, &id)) {
68            mTarget->render((IOMX::buffer_id)id);
69        }
70    }
71
72private:
73    sp<IOMXRenderer> mTarget;
74
75    AwesomeRemoteRenderer(const AwesomeRemoteRenderer &);
76    AwesomeRemoteRenderer &operator=(const AwesomeRemoteRenderer &);
77};
78
79struct AwesomeLocalRenderer : public AwesomeRenderer {
80    AwesomeLocalRenderer(
81            OMX_COLOR_FORMATTYPE colorFormat,
82            const sp<ISurface> &surface,
83            size_t displayWidth, size_t displayHeight,
84            size_t decodedWidth, size_t decodedHeight)
85        : mTarget(new SoftwareRenderer(
86                    colorFormat, surface, displayWidth, displayHeight,
87                    decodedWidth, decodedHeight)) {
88    }
89
90    virtual void render(MediaBuffer *buffer) {
91        mTarget->render(
92                (const uint8_t *)buffer->data() + buffer->range_offset(),
93                buffer->range_length(), NULL);
94    }
95
96protected:
97    virtual ~AwesomeLocalRenderer() {
98        delete mTarget;
99        mTarget = NULL;
100    }
101
102private:
103    SoftwareRenderer *mTarget;
104
105    AwesomeLocalRenderer(const AwesomeLocalRenderer &);
106    AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
107};
108
109AwesomePlayer::AwesomePlayer()
110    : mTimeSource(NULL),
111      mAudioPlayer(NULL),
112      mLastVideoBuffer(NULL),
113      mVideoBuffer(NULL) {
114    CHECK_EQ(mClient.connect(), OK);
115
116    DataSource::RegisterDefaultSniffers();
117
118    mVideoEvent = new AwesomeEvent(this, 0);
119    mVideoEventPending = false;
120    mStreamDoneEvent = new AwesomeEvent(this, 1);
121    mStreamDoneEventPending = false;
122    mBufferingEvent = new AwesomeEvent(this, 2);
123    mBufferingEventPending = false;
124
125    mQueue.start();
126
127    reset();
128}
129
130AwesomePlayer::~AwesomePlayer() {
131    mQueue.stop();
132
133    reset();
134
135    mClient.disconnect();
136}
137
138void AwesomePlayer::cancelPlayerEvents(bool keepBufferingGoing) {
139    mQueue.cancelEvent(mVideoEvent->eventID());
140    mVideoEventPending = false;
141    mQueue.cancelEvent(mStreamDoneEvent->eventID());
142    mStreamDoneEventPending = false;
143
144    if (!keepBufferingGoing) {
145        mQueue.cancelEvent(mBufferingEvent->eventID());
146        mBufferingEventPending = false;
147    }
148}
149
150void AwesomePlayer::setListener(const wp<MediaPlayerBase> &listener) {
151    Mutex::Autolock autoLock(mLock);
152    mListener = listener;
153}
154
155status_t AwesomePlayer::setDataSource(
156        const char *uri, const KeyedVector<String8, String8> *headers) {
157    Mutex::Autolock autoLock(mLock);
158
159    reset_l();
160
161    sp<DataSource> dataSource = DataSource::CreateFromURI(uri, headers);
162
163    if (dataSource == NULL) {
164        return UNKNOWN_ERROR;
165    }
166
167    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
168
169    if (extractor == NULL) {
170        return UNKNOWN_ERROR;
171    }
172
173    if (dataSource->flags() & DataSource::kWantsPrefetching) {
174        mPrefetcher = new Prefetcher;
175    }
176
177    return setDataSource_l(extractor);
178}
179
180status_t AwesomePlayer::setDataSource(
181        int fd, int64_t offset, int64_t length) {
182    Mutex::Autolock autoLock(mLock);
183
184    reset_l();
185
186    sp<DataSource> source = new FileSource(fd, offset, length);
187
188    status_t err = source->initCheck();
189
190    if (err != OK) {
191        return err;
192    }
193
194    sp<MediaExtractor> extractor = MediaExtractor::Create(source);
195
196    if (extractor == NULL) {
197        return UNKNOWN_ERROR;
198    }
199
200    return setDataSource_l(extractor);
201}
202
203status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
204    bool haveAudio = false;
205    bool haveVideo = false;
206    for (size_t i = 0; i < extractor->countTracks(); ++i) {
207        sp<MetaData> meta = extractor->getTrackMetaData(i);
208
209        const char *mime;
210        CHECK(meta->findCString(kKeyMIMEType, &mime));
211
212        if (!haveVideo && !strncasecmp(mime, "video/", 6)) {
213            if (setVideoSource(extractor->getTrack(i)) == OK) {
214                haveVideo = true;
215            }
216        } else if (!haveAudio && !strncasecmp(mime, "audio/", 6)) {
217            if (setAudioSource(extractor->getTrack(i)) == OK) {
218                haveAudio = true;
219            }
220        }
221
222        if (haveAudio && haveVideo) {
223            break;
224        }
225    }
226
227    return !haveAudio && !haveVideo ? UNKNOWN_ERROR : OK;
228}
229
230void AwesomePlayer::reset() {
231    Mutex::Autolock autoLock(mLock);
232    reset_l();
233}
234
235void AwesomePlayer::reset_l() {
236    cancelPlayerEvents();
237
238    mVideoRenderer.clear();
239
240    if (mLastVideoBuffer) {
241        mLastVideoBuffer->release();
242        mLastVideoBuffer = NULL;
243    }
244
245    if (mVideoBuffer) {
246        mVideoBuffer->release();
247        mVideoBuffer = NULL;
248    }
249
250    if (mVideoSource != NULL) {
251        mVideoSource->stop();
252
253        // The following hack is necessary to ensure that the OMX
254        // component is completely released by the time we may try
255        // to instantiate it again.
256        wp<MediaSource> tmp = mVideoSource;
257        mVideoSource.clear();
258        while (tmp.promote() != NULL) {
259            usleep(1000);
260        }
261        IPCThreadState::self()->flushCommands();
262    }
263
264    mAudioSource.clear();
265
266    if (mTimeSource != mAudioPlayer) {
267        delete mTimeSource;
268    }
269    mTimeSource = NULL;
270
271    delete mAudioPlayer;
272    mAudioPlayer = NULL;
273
274    mDurationUs = -1;
275    mFlags = 0;
276    mVideoWidth = mVideoHeight = -1;
277    mTimeSourceDeltaUs = 0;
278    mVideoTimeUs = 0;
279
280    mSeeking = false;
281    mSeekTimeUs = 0;
282
283    mPrefetcher.clear();
284}
285
286// static
287void AwesomePlayer::AudioNotify(void *_me, int what) {
288    AwesomePlayer *me = (AwesomePlayer *)_me;
289
290    Mutex::Autolock autoLock(me->mLock);
291
292    switch (what) {
293        case AudioPlayer::REACHED_EOS:
294            me->postStreamDoneEvent_l();
295            break;
296
297        case AudioPlayer::SEEK_COMPLETE:
298        {
299            me->notifyListener_l(MEDIA_SEEK_COMPLETE);
300            break;
301        }
302
303        default:
304            CHECK(!"should not be here.");
305            break;
306    }
307}
308
309void AwesomePlayer::notifyListener_l(int msg, int ext1) {
310    if (mListener != NULL) {
311        sp<MediaPlayerBase> listener = mListener.promote();
312
313        if (listener != NULL) {
314            listener->sendEvent(msg, ext1);
315        }
316    }
317}
318
319void AwesomePlayer::onBufferingUpdate() {
320    Mutex::Autolock autoLock(mLock);
321    mBufferingEventPending = false;
322
323    if (mDurationUs >= 0) {
324        int64_t cachedDurationUs = mPrefetcher->getCachedDurationUs();
325        int64_t positionUs = 0;
326        if (mVideoRenderer != NULL) {
327            positionUs = mVideoTimeUs;
328        } else if (mAudioPlayer != NULL) {
329            positionUs = mAudioPlayer->getMediaTimeUs();
330        }
331
332        cachedDurationUs += positionUs;
333
334        double percentage = (double)cachedDurationUs / mDurationUs;
335        notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0);
336
337        postBufferingEvent_l();
338    }
339}
340
341void AwesomePlayer::onStreamDone() {
342    // Posted whenever any stream finishes playing.
343
344    Mutex::Autolock autoLock(mLock);
345    mStreamDoneEventPending = false;
346
347    if (mFlags & LOOPING) {
348        seekTo_l(0);
349
350        if (mVideoRenderer != NULL) {
351            postVideoEvent_l();
352        }
353    } else {
354        notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
355
356        pause_l();
357    }
358}
359
360status_t AwesomePlayer::play() {
361    Mutex::Autolock autoLock(mLock);
362
363    if (mFlags & PLAYING) {
364        return OK;
365    }
366
367    mFlags |= PLAYING;
368    mFlags |= FIRST_FRAME;
369
370    bool deferredAudioSeek = false;
371
372    if (mAudioSource != NULL) {
373        if (mAudioPlayer == NULL) {
374            if (mAudioSink != NULL) {
375                mAudioPlayer = new AudioPlayer(mAudioSink);
376
377                mAudioPlayer->setListenerCallback(
378                        &AwesomePlayer::AudioNotify, this);
379
380                mAudioPlayer->setSource(mAudioSource);
381                status_t err = mAudioPlayer->start();
382
383                if (err != OK) {
384                    delete mAudioPlayer;
385                    mAudioPlayer = NULL;
386
387                    mFlags &= ~(PLAYING | FIRST_FRAME);
388
389                    return err;
390                }
391
392                delete mTimeSource;
393                mTimeSource = mAudioPlayer;
394
395                deferredAudioSeek = true;
396            }
397        } else {
398            mAudioPlayer->resume();
399        }
400    }
401
402    if (mTimeSource == NULL && mAudioPlayer == NULL) {
403        mTimeSource = new SystemTimeSource;
404    }
405
406    if (mVideoSource != NULL) {
407        if (mVideoRenderer == NULL) {
408            initRenderer_l();
409        }
410
411        if (mVideoRenderer != NULL) {
412            // Kick off video playback
413            postVideoEvent_l();
414        }
415    }
416
417    if (deferredAudioSeek) {
418        // If there was a seek request while we were paused
419        // and we're just starting up again, honor the request now.
420        seekAudioIfNecessary_l();
421    }
422
423    postBufferingEvent_l();
424
425    return OK;
426}
427
428void AwesomePlayer::initRenderer_l() {
429    if (mISurface != NULL) {
430        sp<MetaData> meta = mVideoSource->getFormat();
431
432        int32_t format;
433        const char *component;
434        int32_t decodedWidth, decodedHeight;
435        CHECK(meta->findInt32(kKeyColorFormat, &format));
436        CHECK(meta->findCString(kKeyDecoderComponent, &component));
437        CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
438        CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
439
440        mVideoRenderer.clear();
441
442        // Must ensure that mVideoRenderer's destructor is actually executed
443        // before creating a new one.
444        IPCThreadState::self()->flushCommands();
445
446        if (!strncmp("OMX.", component, 4)) {
447            // Our OMX codecs allocate buffers on the media_server side
448            // therefore they require a remote IOMXRenderer that knows how
449            // to display them.
450            mVideoRenderer = new AwesomeRemoteRenderer(
451                mClient.interface()->createRenderer(
452                        mISurface, component,
453                        (OMX_COLOR_FORMATTYPE)format,
454                        decodedWidth, decodedHeight,
455                        mVideoWidth, mVideoHeight));
456        } else {
457            // Other decoders are instantiated locally and as a consequence
458            // allocate their buffers in local address space.
459            mVideoRenderer = new AwesomeLocalRenderer(
460                (OMX_COLOR_FORMATTYPE)format,
461                mISurface,
462                mVideoWidth, mVideoHeight,
463                decodedWidth, decodedHeight);
464        }
465    }
466}
467
468status_t AwesomePlayer::pause() {
469    Mutex::Autolock autoLock(mLock);
470    return pause_l();
471}
472
473status_t AwesomePlayer::pause_l() {
474    if (!(mFlags & PLAYING)) {
475        return OK;
476    }
477
478    cancelPlayerEvents(true /* keepBufferingGoing */);
479
480    if (mAudioPlayer != NULL) {
481        mAudioPlayer->pause();
482    }
483
484    mFlags &= ~PLAYING;
485
486    return OK;
487}
488
489bool AwesomePlayer::isPlaying() const {
490    Mutex::Autolock autoLock(mLock);
491
492    return mFlags & PLAYING;
493}
494
495void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
496    Mutex::Autolock autoLock(mLock);
497
498    mISurface = isurface;
499}
500
501void AwesomePlayer::setAudioSink(
502        const sp<MediaPlayerBase::AudioSink> &audioSink) {
503    Mutex::Autolock autoLock(mLock);
504
505    mAudioSink = audioSink;
506}
507
508status_t AwesomePlayer::setLooping(bool shouldLoop) {
509    Mutex::Autolock autoLock(mLock);
510
511    mFlags = mFlags & ~LOOPING;
512
513    if (shouldLoop) {
514        mFlags |= LOOPING;
515    }
516
517    return OK;
518}
519
520status_t AwesomePlayer::getDuration(int64_t *durationUs) {
521    Mutex::Autolock autoLock(mLock);
522
523    if (mDurationUs < 0) {
524        return UNKNOWN_ERROR;
525    }
526
527    *durationUs = mDurationUs;
528
529    return OK;
530}
531
532status_t AwesomePlayer::getPosition(int64_t *positionUs) {
533    Mutex::Autolock autoLock(mLock);
534
535    if (mVideoRenderer != NULL) {
536        *positionUs = mVideoTimeUs;
537    } else if (mAudioPlayer != NULL) {
538        *positionUs = mAudioPlayer->getMediaTimeUs();
539    } else {
540        *positionUs = 0;
541    }
542
543    return OK;
544}
545
546status_t AwesomePlayer::seekTo(int64_t timeUs) {
547    Mutex::Autolock autoLock(mLock);
548    return seekTo_l(timeUs);
549}
550
551status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
552    mSeeking = true;
553    mSeekTimeUs = timeUs;
554
555    seekAudioIfNecessary_l();
556
557    return OK;
558}
559
560void AwesomePlayer::seekAudioIfNecessary_l() {
561    if (mSeeking && mVideoRenderer == NULL && mAudioPlayer != NULL) {
562        mAudioPlayer->seekTo(mSeekTimeUs);
563
564        mSeeking = false;
565    }
566}
567
568status_t AwesomePlayer::getVideoDimensions(
569        int32_t *width, int32_t *height) const {
570    Mutex::Autolock autoLock(mLock);
571
572    if (mVideoWidth < 0 || mVideoHeight < 0) {
573        return UNKNOWN_ERROR;
574    }
575
576    *width = mVideoWidth;
577    *height = mVideoHeight;
578
579    return OK;
580}
581
582status_t AwesomePlayer::setAudioSource(sp<MediaSource> source) {
583    if (source == NULL) {
584        return UNKNOWN_ERROR;
585    }
586
587    if (mPrefetcher != NULL) {
588        source = mPrefetcher->addSource(source);
589    }
590
591    sp<MetaData> meta = source->getFormat();
592
593    const char *mime;
594    CHECK(meta->findCString(kKeyMIMEType, &mime));
595
596    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
597        mAudioSource = source;
598    } else {
599        mAudioSource = OMXCodec::Create(
600                mClient.interface(), source->getFormat(),
601                false, // createEncoder
602                source);
603    }
604
605    if (mAudioSource != NULL) {
606        int64_t durationUs;
607        if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) {
608            if (mDurationUs < 0 || durationUs > mDurationUs) {
609                mDurationUs = durationUs;
610            }
611        }
612    }
613
614    return mAudioSource != NULL ? OK : UNKNOWN_ERROR;
615}
616
617status_t AwesomePlayer::setVideoSource(sp<MediaSource> source) {
618    if (source == NULL) {
619        return UNKNOWN_ERROR;
620    }
621
622    if (mPrefetcher != NULL) {
623        source = mPrefetcher->addSource(source);
624    }
625
626    mVideoSource = OMXCodec::Create(
627            mClient.interface(), source->getFormat(),
628            false, // createEncoder
629            source);
630
631    if (mVideoSource != NULL) {
632        int64_t durationUs;
633        if (source->getFormat()->findInt64(kKeyDuration, &durationUs)) {
634            if (mDurationUs < 0 || durationUs > mDurationUs) {
635                mDurationUs = durationUs;
636            }
637        }
638
639        CHECK(source->getFormat()->findInt32(kKeyWidth, &mVideoWidth));
640        CHECK(source->getFormat()->findInt32(kKeyHeight, &mVideoHeight));
641
642        mVideoSource->start();
643    }
644
645    return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
646}
647
648void AwesomePlayer::onEvent(int32_t code) {
649    if (code == 1) {
650        onStreamDone();
651        return;
652    } else if (code == 2) {
653        onBufferingUpdate();
654        return;
655    }
656
657    Mutex::Autolock autoLock(mLock);
658
659    mVideoEventPending = false;
660
661    if (mSeeking) {
662        if (mLastVideoBuffer) {
663            mLastVideoBuffer->release();
664            mLastVideoBuffer = NULL;
665        }
666
667        if (mVideoBuffer) {
668            mVideoBuffer->release();
669            mVideoBuffer = NULL;
670        }
671    }
672
673    if (!mVideoBuffer) {
674        MediaSource::ReadOptions options;
675        if (mSeeking) {
676            LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
677
678            options.setSeekTo(mSeekTimeUs);
679        }
680        for (;;) {
681            status_t err = mVideoSource->read(&mVideoBuffer, &options);
682            options.clearSeekTo();
683
684            if (err != OK) {
685                CHECK_EQ(mVideoBuffer, NULL);
686
687                if (err == INFO_FORMAT_CHANGED) {
688                    LOGV("VideoSource signalled format change.");
689
690                    initRenderer_l();
691                    continue;
692                }
693
694                postStreamDoneEvent_l();
695                return;
696            }
697
698            if (mVideoBuffer->range_length() == 0) {
699                // Some decoders, notably the PV AVC software decoder
700                // return spurious empty buffers that we just want to ignore.
701
702                mVideoBuffer->release();
703                mVideoBuffer = NULL;
704                continue;
705            }
706
707            break;
708        }
709    }
710
711    int64_t timeUs;
712    CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
713
714    mVideoTimeUs = timeUs;
715
716    if (mSeeking) {
717        if (mAudioPlayer != NULL) {
718            LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
719
720            mAudioPlayer->seekTo(timeUs);
721        } else {
722            // If we're playing video only, report seek complete now,
723            // otherwise audio player will notify us later.
724            notifyListener_l(MEDIA_SEEK_COMPLETE);
725        }
726
727        mFlags |= FIRST_FRAME;
728        mSeeking = false;
729    }
730
731    if (mFlags & FIRST_FRAME) {
732        mFlags &= ~FIRST_FRAME;
733
734        mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs;
735    }
736
737    int64_t realTimeUs, mediaTimeUs;
738    if (mAudioPlayer != NULL
739        && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
740        mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
741    }
742
743    int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs;
744
745    int64_t latenessUs = nowUs - timeUs;
746
747    if (latenessUs > 40000) {
748        // We're more than 40ms late.
749        LOGI("we're late by %lld us (%.2f secs)", latenessUs, latenessUs / 1E6);
750
751        mVideoBuffer->release();
752        mVideoBuffer = NULL;
753
754        postVideoEvent_l();
755        return;
756    }
757
758    if (latenessUs < -10000) {
759        // We're more than 10ms early.
760
761        postVideoEvent_l(10000);
762        return;
763    }
764
765    mVideoRenderer->render(mVideoBuffer);
766
767    if (mLastVideoBuffer) {
768        mLastVideoBuffer->release();
769        mLastVideoBuffer = NULL;
770    }
771    mLastVideoBuffer = mVideoBuffer;
772    mVideoBuffer = NULL;
773
774    postVideoEvent_l();
775}
776
777void AwesomePlayer::postVideoEvent_l(int64_t delayUs) {
778    if (mVideoEventPending) {
779        return;
780    }
781
782    mVideoEventPending = true;
783    mQueue.postEventWithDelay(mVideoEvent, delayUs < 0 ? 10000 : delayUs);
784}
785
786void AwesomePlayer::postStreamDoneEvent_l() {
787    if (mStreamDoneEventPending) {
788        return;
789    }
790    mStreamDoneEventPending = true;
791    mQueue.postEvent(mStreamDoneEvent);
792}
793
794void AwesomePlayer::postBufferingEvent_l() {
795    if (mPrefetcher == NULL) {
796        return;
797    }
798
799    if (mBufferingEventPending) {
800        return;
801    }
802    mBufferingEventPending = true;
803    mQueue.postEventWithDelay(mBufferingEvent, 1000000ll);
804}
805
806}  // namespace android
807
808