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