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