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 namespace android {
31
DecoderBase(const sp<AMessage> & notify)32 NuPlayer::DecoderBase::DecoderBase(const sp<AMessage> ¬ify)
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
~DecoderBase()45 NuPlayer::DecoderBase::~DecoderBase() {
46 stopLooper();
47 }
48
49 static
PostAndAwaitResponse(const sp<AMessage> & msg,sp<AMessage> * response)50 status_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
configure(const sp<AMessage> & format)65 void 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
init()71 void NuPlayer::DecoderBase::init() {
72 mDecoderLooper->registerHandler(this);
73 }
74
stopLooper()75 void NuPlayer::DecoderBase::stopLooper() {
76 mDecoderLooper->unregisterHandler(id());
77 mDecoderLooper->stop();
78 }
79
setParameters(const sp<AMessage> & params)80 void NuPlayer::DecoderBase::setParameters(const sp<AMessage> ¶ms) {
81 sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
82 msg->setMessage("params", params);
83 msg->post();
84 }
85
setRenderer(const sp<Renderer> & renderer)86 void 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
pause()92 void NuPlayer::DecoderBase::pause() {
93 sp<AMessage> msg = new AMessage(kWhatPause, this);
94
95 sp<AMessage> response;
96 PostAndAwaitResponse(msg, &response);
97 }
98
signalFlush()99 void NuPlayer::DecoderBase::signalFlush() {
100 (new AMessage(kWhatFlush, this))->post();
101 }
102
signalResume(bool notifyComplete)103 void NuPlayer::DecoderBase::signalResume(bool notifyComplete) {
104 sp<AMessage> msg = new AMessage(kWhatResume, this);
105 msg->setInt32("notifyComplete", notifyComplete);
106 msg->post();
107 }
108
initiateShutdown()109 void NuPlayer::DecoderBase::initiateShutdown() {
110 (new AMessage(kWhatShutdown, this))->post();
111 }
112
onRequestInputBuffers()113 void 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
onMessageReceived(const sp<AMessage> & msg)127 void 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", ¶ms));
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", ¬ifyComplete));
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
handleError(int32_t err)199 void 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