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