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