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