NuPlayer.cpp revision 53df1a460bcfdd129ca2bc416dee2009e35c042e
1/*
2 * Copyright (C) 2010 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 "NuPlayer"
19#include <utils/Log.h>
20
21#include "NuPlayer.h"
22#include "NuPlayerDecoder.h"
23#include "NuPlayerRenderer.h"
24#include "NuPlayerStreamListener.h"
25
26#include <media/stagefright/foundation/hexdump.h>
27#include <media/stagefright/foundation/ABuffer.h>
28#include <media/stagefright/foundation/ADebug.h>
29#include <media/stagefright/foundation/AMessage.h>
30#include <media/stagefright/ACodec.h>
31#include <media/stagefright/MediaErrors.h>
32#include <media/stagefright/MetaData.h>
33#include <surfaceflinger/Surface.h>
34
35namespace android {
36
37////////////////////////////////////////////////////////////////////////////////
38
39NuPlayer::NuPlayer()
40    : mEOS(false),
41      mAudioEOS(false),
42      mVideoEOS(false),
43      mFlushingAudio(NONE),
44      mFlushingVideo(NONE) {
45}
46
47NuPlayer::~NuPlayer() {
48}
49
50void NuPlayer::setListener(const wp<MediaPlayerBase> &listener) {
51    mListener = listener;
52}
53
54void NuPlayer::setDataSource(const sp<IStreamSource> &source) {
55    sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
56
57    source->incStrong(this);
58    msg->setPointer("source", source.get());  // XXX unsafe.
59
60    msg->post();
61}
62
63void NuPlayer::setVideoSurface(const sp<Surface> &surface) {
64    sp<AMessage> msg = new AMessage(kWhatSetVideoSurface, id());
65    msg->setObject("surface", surface);
66    msg->post();
67}
68
69void NuPlayer::setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink) {
70    sp<AMessage> msg = new AMessage(kWhatSetAudioSink, id());
71    msg->setObject("sink", sink);
72    msg->post();
73}
74
75void NuPlayer::start() {
76    (new AMessage(kWhatStart, id()))->post();
77}
78
79// static
80bool NuPlayer::IsFlushingState(FlushStatus state, bool *formatChange) {
81    switch (state) {
82        case FLUSHING_DECODER:
83            if (formatChange != NULL) {
84                *formatChange = false;
85            }
86            return true;
87
88        case FLUSHING_DECODER_FORMATCHANGE:
89            if (formatChange != NULL) {
90                *formatChange = true;
91            }
92            return true;
93
94        default:
95            return false;
96    }
97}
98
99void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
100    switch (msg->what()) {
101        case kWhatSetDataSource:
102        {
103            LOGI("kWhatSetDataSource");
104
105            CHECK(mSource == NULL);
106
107            void *ptr;
108            CHECK(msg->findPointer("source", &ptr));
109
110            mSource = static_cast<IStreamSource *>(ptr);
111            mSource->decStrong(this);
112
113            mStreamListener = new NuPlayerStreamListener(mSource, id());
114            mTSParser = new ATSParser;
115            break;
116        }
117
118        case kWhatSetVideoSurface:
119        {
120            LOGI("kWhatSetVideoSurface");
121
122            sp<RefBase> obj;
123            CHECK(msg->findObject("surface", &obj));
124
125            mSurface = static_cast<Surface *>(obj.get());
126            break;
127        }
128
129        case kWhatSetAudioSink:
130        {
131            LOGI("kWhatSetAudioSink");
132
133            sp<RefBase> obj;
134            CHECK(msg->findObject("sink", &obj));
135
136            mAudioSink = static_cast<MediaPlayerBase::AudioSink *>(obj.get());
137            break;
138        }
139
140        case kWhatStart:
141        {
142            mStreamListener->start();
143
144            mRenderer = new Renderer(
145                    mAudioSink,
146                    new AMessage(kWhatRendererNotify, id()));
147
148            looper()->registerHandler(mRenderer);
149
150            (new AMessage(kWhatScanSources, id()))->post();
151            break;
152        }
153
154        case kWhatScanSources:
155        {
156            instantiateDecoder(
157                    false,
158                    &mVideoDecoder,
159                    false /* ignoreCodecSpecificData */);
160
161            if (mAudioSink != NULL) {
162                instantiateDecoder(
163                        true,
164                        &mAudioDecoder,
165                        false /* ignoreCodecSpecificData */);
166            }
167
168            if (mEOS) {
169                break;
170            }
171
172            feedMoreTSData();
173
174            if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
175                msg->post(100000ll);
176            }
177            break;
178        }
179
180        case kWhatVideoNotify:
181        case kWhatAudioNotify:
182        {
183            bool audio = msg->what() == kWhatAudioNotify;
184
185            sp<AMessage> codecRequest;
186            CHECK(msg->findMessage("codec-request", &codecRequest));
187
188            int32_t what;
189            CHECK(codecRequest->findInt32("what", &what));
190
191            if (what == ACodec::kWhatFillThisBuffer) {
192                status_t err = feedDecoderInputData(
193                        audio, codecRequest);
194
195                if (err == -EWOULDBLOCK && !mEOS) {
196                    feedMoreTSData();
197                    msg->post();
198                }
199            } else if (what == ACodec::kWhatEOS) {
200                mRenderer->queueEOS(audio, ERROR_END_OF_STREAM);
201            } else if (what == ACodec::kWhatFlushCompleted) {
202                bool formatChange;
203
204                if (audio) {
205                    CHECK(IsFlushingState(mFlushingAudio, &formatChange));
206                    mFlushingAudio = FLUSHED;
207                } else {
208                    CHECK(IsFlushingState(mFlushingVideo, &formatChange));
209                    mFlushingVideo = FLUSHED;
210                }
211
212                LOGI("decoder %s flush completed", audio ? "audio" : "video");
213
214                if (formatChange) {
215                    LOGI("initiating %s decoder shutdown",
216                         audio ? "audio" : "video");
217
218                    (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();
219
220                    if (audio) {
221                        mFlushingAudio = SHUTTING_DOWN_DECODER;
222                    } else {
223                        mFlushingVideo = SHUTTING_DOWN_DECODER;
224                    }
225                }
226
227                finishFlushIfPossible();
228            } else if (what == ACodec::kWhatOutputFormatChanged) {
229                CHECK(audio);
230
231                int32_t numChannels;
232                CHECK(codecRequest->findInt32("channel-count", &numChannels));
233
234                int32_t sampleRate;
235                CHECK(codecRequest->findInt32("sample-rate", &sampleRate));
236
237                LOGI("Audio output format changed to %d Hz, %d channels",
238                     sampleRate, numChannels);
239
240                mAudioSink->close();
241                CHECK_EQ(mAudioSink->open(sampleRate, numChannels), (status_t)OK);
242                mAudioSink->start();
243
244                mRenderer->signalAudioSinkChanged();
245            } else if (what == ACodec::kWhatShutdownCompleted) {
246                LOGI("%s shutdown completed", audio ? "audio" : "video");
247                if (audio) {
248                    mAudioDecoder.clear();
249
250                    CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
251                    mFlushingAudio = SHUT_DOWN;
252                } else {
253                    mVideoDecoder.clear();
254
255                    CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
256                    mFlushingVideo = SHUT_DOWN;
257                }
258
259                finishFlushIfPossible();
260            } else {
261                CHECK_EQ((int)what, (int)ACodec::kWhatDrainThisBuffer);
262
263                renderBuffer(audio, codecRequest);
264            }
265
266            break;
267        }
268
269        case kWhatRendererNotify:
270        {
271            int32_t what;
272            CHECK(msg->findInt32("what", &what));
273
274            if (what == Renderer::kWhatEOS) {
275                int32_t audio;
276                CHECK(msg->findInt32("audio", &audio));
277
278                if (audio) {
279                    mAudioEOS = true;
280                } else {
281                    mVideoEOS = true;
282                }
283
284                LOGI("reached %s EOS", audio ? "audio" : "video");
285
286                if ((mAudioEOS || mAudioDecoder == NULL)
287                        && (mVideoEOS || mVideoDecoder == NULL)) {
288                    notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
289                }
290            } else {
291                CHECK_EQ(what, (int32_t)Renderer::kWhatFlushComplete);
292
293                int32_t audio;
294                CHECK(msg->findInt32("audio", &audio));
295
296                LOGI("renderer %s flush completed.", audio ? "audio" : "video");
297            }
298            break;
299        }
300
301        case kWhatMoreDataQueued:
302        {
303            break;
304        }
305
306        default:
307            TRESPASS();
308            break;
309    }
310}
311
312void NuPlayer::finishFlushIfPossible() {
313    if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {
314        return;
315    }
316
317    if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {
318        return;
319    }
320
321    LOGI("both audio and video are flushed now.");
322
323    mRenderer->signalTimeDiscontinuity();
324
325    if (mFlushingAudio == SHUT_DOWN) {
326        instantiateDecoder(
327                true,
328                &mAudioDecoder,
329                true /* ignoreCodecSpecificData */);
330        CHECK(mAudioDecoder != NULL);
331    } else if (mAudioDecoder != NULL) {
332        mAudioDecoder->signalResume();
333    }
334
335    if (mFlushingVideo == SHUT_DOWN) {
336        instantiateDecoder(
337                false,
338                &mVideoDecoder,
339                true /* ignoreCodecSpecificData */);
340        CHECK(mVideoDecoder != NULL);
341    } else if (mVideoDecoder != NULL) {
342        mVideoDecoder->signalResume();
343    }
344
345    mFlushingAudio = NONE;
346    mFlushingVideo = NONE;
347}
348
349void NuPlayer::feedMoreTSData() {
350    CHECK(!mEOS);
351
352    for (int32_t i = 0; i < 10; ++i) {
353        char buffer[188];
354        ssize_t n = mStreamListener->read(buffer, sizeof(buffer));
355
356        if (n == 0) {
357            LOGI("input data EOS reached.");
358            mTSParser->signalEOS(ERROR_END_OF_STREAM);
359            mEOS = true;
360            break;
361        } else if (n == INFO_DISCONTINUITY) {
362            mTSParser->signalDiscontinuity(ATSParser::DISCONTINUITY_SEEK);
363        } else if (n < 0) {
364            CHECK_EQ(n, -EWOULDBLOCK);
365            break;
366        } else {
367            if (buffer[0] == 0x00) {
368                // XXX legacy
369                mTSParser->signalDiscontinuity(
370                        buffer[1] == 0x00
371                            ? ATSParser::DISCONTINUITY_SEEK
372                            : ATSParser::DISCONTINUITY_FORMATCHANGE);
373            } else {
374                mTSParser->feedTSPacket(buffer, sizeof(buffer));
375            }
376        }
377    }
378}
379
380status_t NuPlayer::dequeueNextAccessUnit(
381        ATSParser::SourceType *type, sp<ABuffer> *accessUnit) {
382    accessUnit->clear();
383
384    status_t audioErr = -EWOULDBLOCK;
385    int64_t audioTimeUs;
386
387    sp<AnotherPacketSource> audioSource =
388        static_cast<AnotherPacketSource *>(
389                mTSParser->getSource(ATSParser::MPEG2ADTS_AUDIO).get());
390
391    if (audioSource != NULL) {
392        audioErr = audioSource->nextBufferTime(&audioTimeUs);
393    }
394
395    status_t videoErr = -EWOULDBLOCK;
396    int64_t videoTimeUs;
397
398    sp<AnotherPacketSource> videoSource =
399        static_cast<AnotherPacketSource *>(
400                mTSParser->getSource(ATSParser::AVC_VIDEO).get());
401
402    if (videoSource != NULL) {
403        videoErr = videoSource->nextBufferTime(&videoTimeUs);
404    }
405
406    if (audioErr == -EWOULDBLOCK || videoErr == -EWOULDBLOCK) {
407        return -EWOULDBLOCK;
408    }
409
410    if (audioErr != OK && videoErr != OK) {
411        return audioErr;
412    }
413
414    if (videoErr != OK || (audioErr == OK && audioTimeUs < videoTimeUs)) {
415        *type = ATSParser::MPEG2ADTS_AUDIO;
416        return audioSource->dequeueAccessUnit(accessUnit);
417    } else {
418        *type = ATSParser::AVC_VIDEO;
419        return videoSource->dequeueAccessUnit(accessUnit);
420    }
421}
422
423status_t NuPlayer::dequeueAccessUnit(
424        ATSParser::SourceType type, sp<ABuffer> *accessUnit) {
425    sp<AnotherPacketSource> source =
426        static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
427
428    if (source == NULL) {
429        return -EWOULDBLOCK;
430    }
431
432    status_t finalResult;
433    if (!source->hasBufferAvailable(&finalResult)) {
434        return finalResult == OK ? -EWOULDBLOCK : finalResult;
435    }
436
437    return source->dequeueAccessUnit(accessUnit);
438}
439
440status_t NuPlayer::instantiateDecoder(
441        bool audio, sp<Decoder> *decoder, bool ignoreCodecSpecificData) {
442    if (*decoder != NULL) {
443        return OK;
444    }
445
446    ATSParser::SourceType type =
447        audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO;
448
449    sp<AnotherPacketSource> source =
450        static_cast<AnotherPacketSource *>(
451                mTSParser->getSource(type).get());
452
453    if (source == NULL) {
454        return -EWOULDBLOCK;
455    }
456
457    sp<AMessage> notify =
458        new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify,
459                     id());
460
461    *decoder = new Decoder(notify, audio ? NULL : mSurface);
462    looper()->registerHandler(*decoder);
463
464    const sp<MetaData> &meta = source->getFormat();
465    (*decoder)->configure(meta, ignoreCodecSpecificData);
466
467    return OK;
468}
469
470status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
471    sp<AMessage> reply;
472    CHECK(msg->findMessage("reply", &reply));
473
474    if ((audio && IsFlushingState(mFlushingAudio))
475            || (!audio && IsFlushingState(mFlushingVideo))) {
476        reply->setInt32("err", INFO_DISCONTINUITY);
477        reply->post();
478        return OK;
479    }
480
481    sp<ABuffer> accessUnit;
482    status_t err = dequeueAccessUnit(
483            audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO,
484            &accessUnit);
485
486    if (err == -EWOULDBLOCK) {
487        return err;
488    } else if (err != OK) {
489        if (err == INFO_DISCONTINUITY) {
490            int32_t formatChange;
491            if (!accessUnit->meta()->findInt32(
492                        "format-change", &formatChange)) {
493                formatChange = 0;
494            }
495
496            LOGI("%s discontinuity (formatChange=%d)",
497                 audio ? "audio" : "video", formatChange);
498
499            (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
500            mRenderer->flush(audio);
501
502            if (audio) {
503                CHECK(mFlushingAudio == NONE
504                        || mFlushingAudio == AWAITING_DISCONTINUITY);
505
506                mFlushingAudio = formatChange
507                    ? FLUSHING_DECODER_FORMATCHANGE : FLUSHING_DECODER;
508
509                if (mFlushingVideo == NONE) {
510                    mFlushingVideo = (mVideoDecoder != NULL)
511                        ? AWAITING_DISCONTINUITY
512                        : FLUSHED;
513                }
514            } else {
515                CHECK(mFlushingVideo == NONE
516                        || mFlushingVideo == AWAITING_DISCONTINUITY);
517
518                mFlushingVideo = formatChange
519                    ? FLUSHING_DECODER_FORMATCHANGE : FLUSHING_DECODER;
520
521                if (mFlushingAudio == NONE) {
522                    mFlushingAudio = (mAudioDecoder != NULL)
523                        ? AWAITING_DISCONTINUITY
524                        : FLUSHED;
525                }
526            }
527        }
528
529        reply->setInt32("err", err);
530        reply->post();
531        return OK;
532    }
533
534    LOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
535
536#if 0
537    int64_t mediaTimeUs;
538    CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
539    LOGI("feeding %s input buffer at media time %.2f secs",
540         audio ? "audio" : "video",
541         mediaTimeUs / 1E6);
542#endif
543
544    reply->setObject("buffer", accessUnit);
545    reply->post();
546
547    return OK;
548}
549
550void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
551    LOGV("renderBuffer %s", audio ? "audio" : "video");
552
553    sp<AMessage> reply;
554    CHECK(msg->findMessage("reply", &reply));
555
556    sp<RefBase> obj;
557    CHECK(msg->findObject("buffer", &obj));
558
559    sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get());
560
561    mRenderer->queueBuffer(audio, buffer, reply);
562}
563
564void NuPlayer::notifyListener(int msg, int ext1, int ext2) {
565    if (mListener == NULL) {
566        return;
567    }
568
569    sp<MediaPlayerBase> listener = mListener.promote();
570
571    if (listener == NULL) {
572        return;
573    }
574
575    listener->sendEvent(msg, ext1, ext2);
576}
577
578}  // namespace android
579