SimplePlayer.cpp revision 31de88566257d5546cf4eee9064d96926a4b0c24
1/*
2 * Copyright (C) 2012 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 "SimplePlayer"
19#include <utils/Log.h>
20
21#include "SimplePlayer.h"
22
23#include <gui/Surface.h>
24
25#include <media/AudioTrack.h>
26#include <media/ICrypto.h>
27#include <media/IMediaHTTPService.h>
28#include <media/stagefright/foundation/ABuffer.h>
29#include <media/stagefright/foundation/ADebug.h>
30#include <media/stagefright/foundation/AMessage.h>
31#include <media/stagefright/MediaCodec.h>
32#include <media/stagefright/MediaErrors.h>
33#include <media/stagefright/NativeWindowWrapper.h>
34#include <media/stagefright/NuMediaExtractor.h>
35
36namespace android {
37
38SimplePlayer::SimplePlayer()
39    : mState(UNINITIALIZED),
40      mDoMoreStuffGeneration(0),
41      mStartTimeRealUs(-1ll) {
42}
43
44SimplePlayer::~SimplePlayer() {
45}
46
47// static
48status_t PostAndAwaitResponse(
49        const sp<AMessage> &msg, sp<AMessage> *response) {
50    status_t err = msg->postAndAwaitResponse(response);
51
52    if (err != OK) {
53        return err;
54    }
55
56    if (!(*response)->findInt32("err", &err)) {
57        err = OK;
58    }
59
60    return err;
61}
62status_t SimplePlayer::setDataSource(const char *path) {
63    sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
64    msg->setString("path", path);
65    sp<AMessage> response;
66    return PostAndAwaitResponse(msg, &response);
67}
68
69status_t SimplePlayer::setSurface(const sp<IGraphicBufferProducer> &bufferProducer) {
70    sp<AMessage> msg = new AMessage(kWhatSetSurface, this);
71
72    sp<Surface> surface;
73    if (bufferProducer != NULL) {
74        surface = new Surface(bufferProducer);
75    }
76
77    msg->setObject(
78            "native-window", new NativeWindowWrapper(surface));
79
80    sp<AMessage> response;
81    return PostAndAwaitResponse(msg, &response);
82}
83
84status_t SimplePlayer::prepare() {
85    sp<AMessage> msg = new AMessage(kWhatPrepare, this);
86    sp<AMessage> response;
87    return PostAndAwaitResponse(msg, &response);
88}
89
90status_t SimplePlayer::start() {
91    sp<AMessage> msg = new AMessage(kWhatStart, this);
92    sp<AMessage> response;
93    return PostAndAwaitResponse(msg, &response);
94}
95
96status_t SimplePlayer::stop() {
97    sp<AMessage> msg = new AMessage(kWhatStop, this);
98    sp<AMessage> response;
99    return PostAndAwaitResponse(msg, &response);
100}
101
102status_t SimplePlayer::reset() {
103    sp<AMessage> msg = new AMessage(kWhatReset, this);
104    sp<AMessage> response;
105    return PostAndAwaitResponse(msg, &response);
106}
107
108void SimplePlayer::onMessageReceived(const sp<AMessage> &msg) {
109    switch (msg->what()) {
110        case kWhatSetDataSource:
111        {
112            status_t err;
113            if (mState != UNINITIALIZED) {
114                err = INVALID_OPERATION;
115            } else {
116                CHECK(msg->findString("path", &mPath));
117                mState = UNPREPARED;
118            }
119
120            sp<AReplyToken> replyID;
121            CHECK(msg->senderAwaitsResponse(&replyID));
122
123            sp<AMessage> response = new AMessage;
124            response->setInt32("err", err);
125            response->postReply(replyID);
126            break;
127        }
128
129        case kWhatSetSurface:
130        {
131            status_t err;
132            if (mState != UNPREPARED) {
133                err = INVALID_OPERATION;
134            } else {
135                sp<RefBase> obj;
136                CHECK(msg->findObject("native-window", &obj));
137
138                mNativeWindow = static_cast<NativeWindowWrapper *>(obj.get());
139
140                err = OK;
141            }
142
143            sp<AReplyToken> replyID;
144            CHECK(msg->senderAwaitsResponse(&replyID));
145
146            sp<AMessage> response = new AMessage;
147            response->setInt32("err", err);
148            response->postReply(replyID);
149            break;
150        }
151
152        case kWhatPrepare:
153        {
154            status_t err;
155            if (mState != UNPREPARED) {
156                err = INVALID_OPERATION;
157            } else {
158                err = onPrepare();
159
160                if (err == OK) {
161                    mState = STOPPED;
162                }
163            }
164
165            sp<AReplyToken> replyID;
166            CHECK(msg->senderAwaitsResponse(&replyID));
167
168            sp<AMessage> response = new AMessage;
169            response->setInt32("err", err);
170            response->postReply(replyID);
171            break;
172        }
173
174        case kWhatStart:
175        {
176            status_t err = OK;
177
178            if (mState == UNPREPARED) {
179                err = onPrepare();
180
181                if (err == OK) {
182                    mState = STOPPED;
183                }
184            }
185
186            if (err == OK) {
187                if (mState != STOPPED) {
188                    err = INVALID_OPERATION;
189                } else {
190                    err = onStart();
191
192                    if (err == OK) {
193                        mState = STARTED;
194                    }
195                }
196            }
197
198            sp<AReplyToken> replyID;
199            CHECK(msg->senderAwaitsResponse(&replyID));
200
201            sp<AMessage> response = new AMessage;
202            response->setInt32("err", err);
203            response->postReply(replyID);
204            break;
205        }
206
207        case kWhatStop:
208        {
209            status_t err;
210
211            if (mState != STARTED) {
212                err = INVALID_OPERATION;
213            } else {
214                err = onStop();
215
216                if (err == OK) {
217                    mState = STOPPED;
218                }
219            }
220
221            sp<AReplyToken> replyID;
222            CHECK(msg->senderAwaitsResponse(&replyID));
223
224            sp<AMessage> response = new AMessage;
225            response->setInt32("err", err);
226            response->postReply(replyID);
227            break;
228        }
229
230        case kWhatReset:
231        {
232            status_t err = OK;
233
234            if (mState == STARTED) {
235                CHECK_EQ(onStop(), (status_t)OK);
236                mState = STOPPED;
237            }
238
239            if (mState == STOPPED) {
240                err = onReset();
241                mState = UNINITIALIZED;
242            }
243
244            sp<AReplyToken> replyID;
245            CHECK(msg->senderAwaitsResponse(&replyID));
246
247            sp<AMessage> response = new AMessage;
248            response->setInt32("err", err);
249            response->postReply(replyID);
250            break;
251        }
252
253        case kWhatDoMoreStuff:
254        {
255            int32_t generation;
256            CHECK(msg->findInt32("generation", &generation));
257
258            if (generation != mDoMoreStuffGeneration) {
259                break;
260            }
261
262            status_t err = onDoMoreStuff();
263
264            if (err == OK) {
265                msg->post(10000ll);
266            }
267            break;
268        }
269
270        default:
271            TRESPASS();
272    }
273}
274
275status_t SimplePlayer::onPrepare() {
276    CHECK_EQ(mState, UNPREPARED);
277
278    mExtractor = new NuMediaExtractor;
279
280    status_t err = mExtractor->setDataSource(
281            NULL /* httpService */, mPath.c_str());
282
283    if (err != OK) {
284        mExtractor.clear();
285        return err;
286    }
287
288    if (mCodecLooper == NULL) {
289        mCodecLooper = new ALooper;
290        mCodecLooper->start();
291    }
292
293    bool haveAudio = false;
294    bool haveVideo = false;
295    for (size_t i = 0; i < mExtractor->countTracks(); ++i) {
296        sp<AMessage> format;
297        status_t err = mExtractor->getTrackFormat(i, &format);
298        CHECK_EQ(err, (status_t)OK);
299
300        AString mime;
301        CHECK(format->findString("mime", &mime));
302
303        bool isVideo = !strncasecmp(mime.c_str(), "video/", 6);
304
305        if (!haveAudio && !strncasecmp(mime.c_str(), "audio/", 6)) {
306            haveAudio = true;
307        } else if (!haveVideo && isVideo) {
308            haveVideo = true;
309        } else {
310            continue;
311        }
312
313        err = mExtractor->selectTrack(i);
314        CHECK_EQ(err, (status_t)OK);
315
316        CodecState *state =
317            &mStateByTrackIndex.editValueAt(
318                    mStateByTrackIndex.add(i, CodecState()));
319
320        state->mNumFramesWritten = 0;
321        state->mCodec = MediaCodec::CreateByType(
322                mCodecLooper, mime.c_str(), false /* encoder */);
323
324        CHECK(state->mCodec != NULL);
325
326        err = state->mCodec->configure(
327                format,
328                isVideo ? mNativeWindow->getSurfaceTextureClient() : NULL,
329                NULL /* crypto */,
330                0 /* flags */);
331
332        CHECK_EQ(err, (status_t)OK);
333
334        size_t j = 0;
335        sp<ABuffer> buffer;
336        while (format->findBuffer(AStringPrintf("csd-%d", j).c_str(), &buffer)) {
337            state->mCSD.push_back(buffer);
338
339            ++j;
340        }
341    }
342
343    for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) {
344        CodecState *state = &mStateByTrackIndex.editValueAt(i);
345
346        status_t err = state->mCodec->start();
347        CHECK_EQ(err, (status_t)OK);
348
349        err = state->mCodec->getInputBuffers(&state->mBuffers[0]);
350        CHECK_EQ(err, (status_t)OK);
351
352        err = state->mCodec->getOutputBuffers(&state->mBuffers[1]);
353        CHECK_EQ(err, (status_t)OK);
354
355        for (size_t j = 0; j < state->mCSD.size(); ++j) {
356            const sp<ABuffer> &srcBuffer = state->mCSD.itemAt(j);
357
358            size_t index;
359            err = state->mCodec->dequeueInputBuffer(&index, -1ll);
360            CHECK_EQ(err, (status_t)OK);
361
362            const sp<ABuffer> &dstBuffer = state->mBuffers[0].itemAt(index);
363
364            CHECK_LE(srcBuffer->size(), dstBuffer->capacity());
365            dstBuffer->setRange(0, srcBuffer->size());
366            memcpy(dstBuffer->data(), srcBuffer->data(), srcBuffer->size());
367
368            err = state->mCodec->queueInputBuffer(
369                    index,
370                    0,
371                    dstBuffer->size(),
372                    0ll,
373                    MediaCodec::BUFFER_FLAG_CODECCONFIG);
374            CHECK_EQ(err, (status_t)OK);
375        }
376    }
377
378    return OK;
379}
380
381status_t SimplePlayer::onStart() {
382    CHECK_EQ(mState, STOPPED);
383
384    mStartTimeRealUs = -1ll;
385
386    sp<AMessage> msg = new AMessage(kWhatDoMoreStuff, this);
387    msg->setInt32("generation", ++mDoMoreStuffGeneration);
388    msg->post();
389
390    return OK;
391}
392
393status_t SimplePlayer::onStop() {
394    CHECK_EQ(mState, STARTED);
395
396    ++mDoMoreStuffGeneration;
397
398    return OK;
399}
400
401status_t SimplePlayer::onReset() {
402    CHECK_EQ(mState, STOPPED);
403
404    for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) {
405        CodecState *state = &mStateByTrackIndex.editValueAt(i);
406
407        CHECK_EQ(state->mCodec->release(), (status_t)OK);
408    }
409
410    mStartTimeRealUs = -1ll;
411
412    mStateByTrackIndex.clear();
413    mCodecLooper.clear();
414    mExtractor.clear();
415    mNativeWindow.clear();
416    mPath.clear();
417
418    return OK;
419}
420
421status_t SimplePlayer::onDoMoreStuff() {
422    ALOGV("onDoMoreStuff");
423    for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) {
424        CodecState *state = &mStateByTrackIndex.editValueAt(i);
425
426        status_t err;
427        do {
428            size_t index;
429            err = state->mCodec->dequeueInputBuffer(&index);
430
431            if (err == OK) {
432                ALOGV("dequeued input buffer on track %zu",
433                      mStateByTrackIndex.keyAt(i));
434
435                state->mAvailInputBufferIndices.push_back(index);
436            } else {
437                ALOGV("dequeueInputBuffer on track %zu returned %d",
438                      mStateByTrackIndex.keyAt(i), err);
439            }
440        } while (err == OK);
441
442        do {
443            BufferInfo info;
444            err = state->mCodec->dequeueOutputBuffer(
445                    &info.mIndex,
446                    &info.mOffset,
447                    &info.mSize,
448                    &info.mPresentationTimeUs,
449                    &info.mFlags);
450
451            if (err == OK) {
452                ALOGV("dequeued output buffer on track %zu",
453                      mStateByTrackIndex.keyAt(i));
454
455                state->mAvailOutputBufferInfos.push_back(info);
456            } else if (err == INFO_FORMAT_CHANGED) {
457                err = onOutputFormatChanged(mStateByTrackIndex.keyAt(i), state);
458                CHECK_EQ(err, (status_t)OK);
459            } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) {
460                err = state->mCodec->getOutputBuffers(&state->mBuffers[1]);
461                CHECK_EQ(err, (status_t)OK);
462            } else {
463                ALOGV("dequeueOutputBuffer on track %zu returned %d",
464                      mStateByTrackIndex.keyAt(i), err);
465            }
466        } while (err == OK
467                || err == INFO_FORMAT_CHANGED
468                || err == INFO_OUTPUT_BUFFERS_CHANGED);
469    }
470
471    for (;;) {
472        size_t trackIndex;
473        status_t err = mExtractor->getSampleTrackIndex(&trackIndex);
474
475        if (err != OK) {
476            ALOGI("encountered input EOS.");
477            break;
478        } else {
479            CodecState *state = &mStateByTrackIndex.editValueFor(trackIndex);
480
481            if (state->mAvailInputBufferIndices.empty()) {
482                break;
483            }
484
485            size_t index = *state->mAvailInputBufferIndices.begin();
486            state->mAvailInputBufferIndices.erase(
487                    state->mAvailInputBufferIndices.begin());
488
489            const sp<ABuffer> &dstBuffer =
490                state->mBuffers[0].itemAt(index);
491
492            err = mExtractor->readSampleData(dstBuffer);
493            CHECK_EQ(err, (status_t)OK);
494
495            int64_t timeUs;
496            CHECK_EQ(mExtractor->getSampleTime(&timeUs), (status_t)OK);
497
498            err = state->mCodec->queueInputBuffer(
499                    index,
500                    dstBuffer->offset(),
501                    dstBuffer->size(),
502                    timeUs,
503                    0);
504            CHECK_EQ(err, (status_t)OK);
505
506            ALOGV("enqueued input data on track %zu", trackIndex);
507
508            err = mExtractor->advance();
509            CHECK_EQ(err, (status_t)OK);
510        }
511    }
512
513    int64_t nowUs = ALooper::GetNowUs();
514
515    if (mStartTimeRealUs < 0ll) {
516        mStartTimeRealUs = nowUs + 1000000ll;
517    }
518
519    for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) {
520        CodecState *state = &mStateByTrackIndex.editValueAt(i);
521
522        while (!state->mAvailOutputBufferInfos.empty()) {
523            BufferInfo *info = &*state->mAvailOutputBufferInfos.begin();
524
525            int64_t whenRealUs = info->mPresentationTimeUs + mStartTimeRealUs;
526            int64_t lateByUs = nowUs - whenRealUs;
527
528            if (lateByUs > -10000ll) {
529                bool release = true;
530
531                if (lateByUs > 30000ll) {
532                    ALOGI("track %zu buffer late by %lld us, dropping.",
533                          mStateByTrackIndex.keyAt(i), (long long)lateByUs);
534                    state->mCodec->releaseOutputBuffer(info->mIndex);
535                } else {
536                    if (state->mAudioTrack != NULL) {
537                        const sp<ABuffer> &srcBuffer =
538                            state->mBuffers[1].itemAt(info->mIndex);
539
540                        renderAudio(state, info, srcBuffer);
541
542                        if (info->mSize > 0) {
543                            release = false;
544                        }
545                    }
546
547                    if (release) {
548                        state->mCodec->renderOutputBufferAndRelease(
549                                info->mIndex);
550                    }
551                }
552
553                if (release) {
554                    state->mAvailOutputBufferInfos.erase(
555                            state->mAvailOutputBufferInfos.begin());
556
557                    info = NULL;
558                } else {
559                    break;
560                }
561            } else {
562                ALOGV("track %zu buffer early by %lld us.",
563                      mStateByTrackIndex.keyAt(i), (long long)-lateByUs);
564                break;
565            }
566        }
567    }
568
569    return OK;
570}
571
572status_t SimplePlayer::onOutputFormatChanged(
573        size_t trackIndex __unused, CodecState *state) {
574    sp<AMessage> format;
575    status_t err = state->mCodec->getOutputFormat(&format);
576
577    if (err != OK) {
578        return err;
579    }
580
581    AString mime;
582    CHECK(format->findString("mime", &mime));
583
584    if (!strncasecmp(mime.c_str(), "audio/", 6)) {
585        int32_t channelCount;
586        int32_t sampleRate;
587        CHECK(format->findInt32("channel-count", &channelCount));
588        CHECK(format->findInt32("sample-rate", &sampleRate));
589
590        state->mAudioTrack = new AudioTrack(
591                AUDIO_STREAM_MUSIC,
592                sampleRate,
593                AUDIO_FORMAT_PCM_16_BIT,
594                audio_channel_out_mask_from_count(channelCount),
595                0);
596
597        state->mNumFramesWritten = 0;
598    }
599
600    return OK;
601}
602
603void SimplePlayer::renderAudio(
604        CodecState *state, BufferInfo *info, const sp<ABuffer> &buffer) {
605    CHECK(state->mAudioTrack != NULL);
606
607    if (state->mAudioTrack->stopped()) {
608        state->mAudioTrack->start();
609    }
610
611    uint32_t numFramesPlayed;
612    CHECK_EQ(state->mAudioTrack->getPosition(&numFramesPlayed), (status_t)OK);
613
614    uint32_t numFramesAvailableToWrite =
615        state->mAudioTrack->frameCount()
616            - (state->mNumFramesWritten - numFramesPlayed);
617
618    size_t numBytesAvailableToWrite =
619        numFramesAvailableToWrite * state->mAudioTrack->frameSize();
620
621    size_t copy = info->mSize;
622    if (copy > numBytesAvailableToWrite) {
623        copy = numBytesAvailableToWrite;
624    }
625
626    if (copy == 0) {
627        return;
628    }
629
630    int64_t startTimeUs = ALooper::GetNowUs();
631
632    ssize_t nbytes = state->mAudioTrack->write(
633            buffer->base() + info->mOffset, copy);
634
635    CHECK_EQ(nbytes, (ssize_t)copy);
636
637    int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
638
639    uint32_t numFramesWritten = nbytes / state->mAudioTrack->frameSize();
640
641    if (delayUs > 2000ll) {
642        ALOGW("AudioTrack::write took %lld us, numFramesAvailableToWrite=%u, "
643              "numFramesWritten=%u",
644              (long long)delayUs, numFramesAvailableToWrite, numFramesWritten);
645    }
646
647    info->mOffset += nbytes;
648    info->mSize -= nbytes;
649
650    state->mNumFramesWritten += numFramesWritten;
651}
652
653}  // namespace android
654