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