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