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