NuPlayerDecoderBase.cpp revision e1e5d7a3d3d4d6d644e6c731f977422e004140d5
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 "NuPlayerDecoderBase"
19#include <utils/Log.h>
20#include <inttypes.h>
21
22#include "NuPlayerDecoderBase.h"
23
24#include "NuPlayerRenderer.h"
25
26#include <media/stagefright/foundation/ADebug.h>
27#include <media/stagefright/foundation/AMessage.h>
28
29namespace android {
30
31NuPlayer::DecoderBase::DecoderBase(const sp<AMessage> &notify)
32    :  mNotify(notify),
33       mBufferGeneration(0),
34       mStats(new AMessage),
35       mRequestInputBuffersPending(false) {
36    // Every decoder has its own looper because MediaCodec operations
37    // are blocking, but NuPlayer needs asynchronous operations.
38    mDecoderLooper = new ALooper;
39    mDecoderLooper->setName("NPDecoder");
40    mDecoderLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
41}
42
43NuPlayer::DecoderBase::~DecoderBase() {
44    mDecoderLooper->unregisterHandler(id());
45    mDecoderLooper->stop();
46}
47
48static
49status_t PostAndAwaitResponse(
50        const sp<AMessage> &msg, sp<AMessage> *response) {
51    status_t err = msg->postAndAwaitResponse(response);
52
53    if (err != OK) {
54        return err;
55    }
56
57    if (!(*response)->findInt32("err", &err)) {
58        err = OK;
59    }
60
61    return err;
62}
63
64void NuPlayer::DecoderBase::configure(const sp<AMessage> &format) {
65    sp<AMessage> msg = new AMessage(kWhatConfigure, this);
66    msg->setMessage("format", format);
67    msg->post();
68}
69
70void NuPlayer::DecoderBase::init() {
71    mDecoderLooper->registerHandler(this);
72}
73
74void NuPlayer::DecoderBase::setParameters(const sp<AMessage> &params) {
75    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
76    msg->setMessage("params", params);
77    msg->post();
78}
79
80void NuPlayer::DecoderBase::setRenderer(const sp<Renderer> &renderer) {
81    sp<AMessage> msg = new AMessage(kWhatSetRenderer, this);
82    msg->setObject("renderer", renderer);
83    msg->post();
84}
85
86status_t NuPlayer::DecoderBase::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
87    sp<AMessage> msg = new AMessage(kWhatGetInputBuffers, this);
88    msg->setPointer("buffers", buffers);
89
90    sp<AMessage> response;
91    return PostAndAwaitResponse(msg, &response);
92}
93
94void NuPlayer::DecoderBase::signalFlush() {
95    (new AMessage(kWhatFlush, this))->post();
96}
97
98void NuPlayer::DecoderBase::signalResume(bool notifyComplete) {
99    sp<AMessage> msg = new AMessage(kWhatResume, this);
100    msg->setInt32("notifyComplete", notifyComplete);
101    msg->post();
102}
103
104void NuPlayer::DecoderBase::initiateShutdown() {
105    (new AMessage(kWhatShutdown, this))->post();
106}
107
108void NuPlayer::DecoderBase::onRequestInputBuffers() {
109    if (mRequestInputBuffersPending) {
110        return;
111    }
112
113    // doRequestBuffers() return true if we should request more data
114    if (doRequestBuffers()) {
115        mRequestInputBuffersPending = true;
116
117        sp<AMessage> msg = new AMessage(kWhatRequestInputBuffers, this);
118        msg->post(10 * 1000ll);
119    }
120}
121
122void NuPlayer::DecoderBase::onMessageReceived(const sp<AMessage> &msg) {
123
124    switch (msg->what()) {
125        case kWhatConfigure:
126        {
127            sp<AMessage> format;
128            CHECK(msg->findMessage("format", &format));
129            onConfigure(format);
130            break;
131        }
132
133        case kWhatSetParameters:
134        {
135            sp<AMessage> params;
136            CHECK(msg->findMessage("params", &params));
137            onSetParameters(params);
138            break;
139        }
140
141        case kWhatSetRenderer:
142        {
143            sp<RefBase> obj;
144            CHECK(msg->findObject("renderer", &obj));
145            onSetRenderer(static_cast<Renderer *>(obj.get()));
146            break;
147        }
148
149        case kWhatGetInputBuffers:
150        {
151            sp<AReplyToken> replyID;
152            CHECK(msg->senderAwaitsResponse(&replyID));
153
154            Vector<sp<ABuffer> > *dstBuffers;
155            CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
156
157            onGetInputBuffers(dstBuffers);
158
159            (new AMessage)->postReply(replyID);
160            break;
161        }
162
163        case kWhatRequestInputBuffers:
164        {
165            mRequestInputBuffersPending = false;
166            onRequestInputBuffers();
167            break;
168        }
169
170        case kWhatFlush:
171        {
172            onFlush();
173            break;
174        }
175
176        case kWhatResume:
177        {
178            int32_t notifyComplete;
179            CHECK(msg->findInt32("notifyComplete", &notifyComplete));
180
181            onResume(notifyComplete);
182            break;
183        }
184
185        case kWhatShutdown:
186        {
187            onShutdown(true);
188            break;
189        }
190
191        default:
192            TRESPASS();
193            break;
194    }
195}
196
197void NuPlayer::DecoderBase::handleError(int32_t err)
198{
199    // We cannot immediately release the codec due to buffers still outstanding
200    // in the renderer.  We signal to the player the error so it can shutdown/release the
201    // decoder after flushing and increment the generation to discard unnecessary messages.
202
203    ++mBufferGeneration;
204
205    sp<AMessage> notify = mNotify->dup();
206    notify->setInt32("what", kWhatError);
207    notify->setInt32("err", err);
208    notify->post();
209}
210
211}  // namespace android
212
213