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