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> &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 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> &params) {
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", &params));
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", &notifyComplete));
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