SimplePlayer.cpp revision 2d8bedd05437b6fccdbc6bf70f673ffd86744d59
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(5000ll);
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->stop(), (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    for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) {
415        CodecState *state = &mStateByTrackIndex.editValueAt(i);
416
417        size_t index;
418        status_t err = state->mCodec->dequeueInputBuffer(&index);
419
420        if (err == OK) {
421            state->mAvailInputBufferIndices.push_back(index);
422        }
423
424        BufferInfo info;
425        err = state->mCodec->dequeueOutputBuffer(
426                &info.mIndex,
427                &info.mOffset,
428                &info.mSize,
429                &info.mPresentationTimeUs,
430                &info.mFlags);
431
432        if (err == OK) {
433            state->mAvailOutputBufferInfos.push_back(info);
434        } else if (err == INFO_FORMAT_CHANGED) {
435            err = onOutputFormatChanged(mStateByTrackIndex.keyAt(i), state);
436            CHECK_EQ(err, (status_t)OK);
437        } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) {
438            err = state->mCodec->getOutputBuffers(&state->mBuffers[1]);
439            CHECK_EQ(err, (status_t)OK);
440        }
441    }
442
443    for (;;) {
444        size_t trackIndex;
445        status_t err = mExtractor->getSampleTrackIndex(&trackIndex);
446
447        if (err != OK) {
448            ALOGI("encountered input EOS.");
449            break;
450        } else {
451            CodecState *state = &mStateByTrackIndex.editValueFor(trackIndex);
452
453            if (state->mAvailInputBufferIndices.empty()) {
454                break;
455            }
456
457            size_t index = *state->mAvailInputBufferIndices.begin();
458            state->mAvailInputBufferIndices.erase(
459                    state->mAvailInputBufferIndices.begin());
460
461            const sp<ABuffer> &dstBuffer =
462                state->mBuffers[0].itemAt(index);
463
464            err = mExtractor->readSampleData(dstBuffer);
465            CHECK_EQ(err, (status_t)OK);
466
467            int64_t timeUs;
468            CHECK_EQ(mExtractor->getSampleTime(&timeUs), (status_t)OK);
469
470            err = state->mCodec->queueInputBuffer(
471                    index,
472                    dstBuffer->offset(),
473                    dstBuffer->size(),
474                    timeUs,
475                    0);
476            CHECK_EQ(err, (status_t)OK);
477
478            err = mExtractor->advance();
479            CHECK_EQ(err, (status_t)OK);
480        }
481    }
482
483    int64_t nowUs = ALooper::GetNowUs();
484
485    if (mStartTimeRealUs < 0ll) {
486        mStartTimeRealUs = nowUs + 1000000ll;
487    }
488
489    for (size_t i = 0; i < mStateByTrackIndex.size(); ++i) {
490        CodecState *state = &mStateByTrackIndex.editValueAt(i);
491
492        while (!state->mAvailOutputBufferInfos.empty()) {
493            BufferInfo *info = &*state->mAvailOutputBufferInfos.begin();
494
495            int64_t whenRealUs = info->mPresentationTimeUs + mStartTimeRealUs;
496            int64_t lateByUs = nowUs - whenRealUs;
497
498            if (lateByUs > -10000ll) {
499                bool release = true;
500
501                if (lateByUs > 30000ll) {
502                    ALOGI("track %d buffer late by %lld us, dropping.",
503                          i, lateByUs);
504                    state->mCodec->releaseOutputBuffer(info->mIndex);
505                } else {
506                    if (state->mAudioTrack != NULL) {
507                        const sp<ABuffer> &srcBuffer =
508                            state->mBuffers[1].itemAt(info->mIndex);
509
510                        renderAudio(state, info, srcBuffer);
511
512                        if (info->mSize > 0) {
513                            release = false;
514                        }
515                    }
516
517                    if (release) {
518                        state->mCodec->renderOutputBufferAndRelease(
519                                info->mIndex);
520                    }
521                }
522
523                if (release) {
524                    state->mAvailOutputBufferInfos.erase(
525                            state->mAvailOutputBufferInfos.begin());
526
527                    info = NULL;
528                } else {
529                    break;
530                }
531            } else {
532                ALOGV("track %d buffer early by %lld us.", i, -lateByUs);
533                break;
534            }
535        }
536    }
537
538    return OK;
539}
540
541status_t SimplePlayer::onOutputFormatChanged(
542        size_t trackIndex, CodecState *state) {
543    sp<AMessage> format;
544    status_t err = state->mCodec->getOutputFormat(&format);
545
546    if (err != OK) {
547        return err;
548    }
549
550    AString mime;
551    CHECK(format->findString("mime", &mime));
552
553    if (!strncasecmp(mime.c_str(), "audio/", 6)) {
554        int32_t channelCount;
555        int32_t sampleRate;
556        CHECK(format->findInt32("channel-count", &channelCount));
557        CHECK(format->findInt32("sample-rate", &sampleRate));
558
559        state->mAudioTrack = new AudioTrack(
560                AUDIO_STREAM_MUSIC,
561                sampleRate,
562                AUDIO_FORMAT_PCM_16_BIT,
563                (channelCount == 1)
564                    ? AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO,
565                0);
566
567        state->mNumFramesWritten = 0;
568    }
569
570    return OK;
571}
572
573void SimplePlayer::renderAudio(
574        CodecState *state, BufferInfo *info, const sp<ABuffer> &buffer) {
575    CHECK(state->mAudioTrack != NULL);
576
577    if (state->mAudioTrack->stopped()) {
578        state->mAudioTrack->start();
579    }
580
581    uint32_t numFramesPlayed;
582    CHECK_EQ(state->mAudioTrack->getPosition(&numFramesPlayed), (status_t)OK);
583
584    uint32_t numFramesAvailableToWrite =
585        state->mAudioTrack->frameCount()
586            - (state->mNumFramesWritten - numFramesPlayed);
587
588    size_t numBytesAvailableToWrite =
589        numFramesAvailableToWrite * state->mAudioTrack->frameSize();
590
591    size_t copy = info->mSize;
592    if (copy > numBytesAvailableToWrite) {
593        copy = numBytesAvailableToWrite;
594    }
595
596    if (copy == 0) {
597        return;
598    }
599
600    int64_t startTimeUs = ALooper::GetNowUs();
601
602    ssize_t nbytes = state->mAudioTrack->write(
603            buffer->base() + info->mOffset, copy);
604
605    CHECK_EQ(nbytes, (ssize_t)copy);
606
607    int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
608
609    uint32_t numFramesWritten = nbytes / state->mAudioTrack->frameSize();
610
611    if (delayUs > 2000ll) {
612        ALOGW("AudioTrack::write took %lld us, numFramesAvailableToWrite=%u, "
613              "numFramesWritten=%u",
614              delayUs, numFramesAvailableToWrite, numFramesWritten);
615    }
616
617    info->mOffset += nbytes;
618    info->mSize -= nbytes;
619
620    state->mNumFramesWritten += numFramesWritten;
621}
622
623}  // namespace android
624