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