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