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