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