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