blob: eec6960d92d477b203f9470529fe72315bf1c0a5 [file] [log] [blame]
Wei Jiabc2fb722014-07-08 16:37:57 -07001/*
2 * Copyright (C) 2014 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 "NuPlayerDecoderPassThrough"
19#include <utils/Log.h>
20#include <inttypes.h>
21
22#include "NuPlayerDecoderPassThrough.h"
23
24#include <media/ICrypto.h>
25#include <media/stagefright/foundation/ABuffer.h>
26#include <media/stagefright/foundation/ADebug.h>
27#include <media/stagefright/foundation/AMessage.h>
28#include <media/stagefright/MediaDefs.h>
29#include <media/stagefright/MediaErrors.h>
30
31namespace android {
32
33static const int kMaxPendingBuffers = 10;
34
35NuPlayer::DecoderPassThrough::DecoderPassThrough(
36 const sp<AMessage> &notify)
37 : Decoder(notify),
38 mNotify(notify),
39 mBufferGeneration(0),
40 mReachedEOS(true),
41 mPendingBuffers(0),
42 mComponentName("pass through decoder") {
43 mDecoderLooper = new ALooper;
44 mDecoderLooper->setName("NuPlayerDecoderPassThrough");
45 mDecoderLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
46}
47
48NuPlayer::DecoderPassThrough::~DecoderPassThrough() {
49}
50
51void NuPlayer::DecoderPassThrough::configure(const sp<AMessage> &format) {
52 sp<AMessage> msg = new AMessage(kWhatConfigure, id());
53 msg->setMessage("format", format);
54 msg->post();
55}
56
57void NuPlayer::DecoderPassThrough::init() {
58 mDecoderLooper->registerHandler(this);
59}
60
61void NuPlayer::DecoderPassThrough::signalFlush() {
62 (new AMessage(kWhatFlush, id()))->post();
63}
64
65void NuPlayer::DecoderPassThrough::signalResume() {
66 (new AMessage(kWhatResume, id()))->post();
67}
68
69void NuPlayer::DecoderPassThrough::initiateShutdown() {
70 (new AMessage(kWhatShutdown, id()))->post();
71}
72
73bool NuPlayer::DecoderPassThrough::supportsSeamlessFormatChange(
74 const sp<AMessage> & /* targetFormat */) const {
75 return true;
76}
77
78void NuPlayer::DecoderPassThrough::onConfigure(const sp<AMessage> &format) {
79 ALOGV("[%s] onConfigure", mComponentName.c_str());
80 mPendingBuffers = 0;
81 mReachedEOS = false;
82 ++mBufferGeneration;
83
84 requestABuffer();
85
86 sp<AMessage> notify = mNotify->dup();
87 notify->setInt32("what", kWhatOutputFormatChanged);
88 notify->setMessage("format", format);
89 notify->post();
90}
91
92bool NuPlayer::DecoderPassThrough::isStaleReply(const sp<AMessage> &msg) {
93 int32_t generation;
94 CHECK(msg->findInt32("generation", &generation));
95 return generation != mBufferGeneration;
96}
97
98void NuPlayer::DecoderPassThrough::requestABuffer() {
99 if (mPendingBuffers >= kMaxPendingBuffers || mReachedEOS) {
100 ALOGV("[%s] mReachedEOS=%d, max pending buffers(%d:%d)",
101 mComponentName.c_str(), (mReachedEOS ? 1 : 0),
102 mPendingBuffers, kMaxPendingBuffers);
103 return;
104 }
105
106 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, id());
107 reply->setInt32("generation", mBufferGeneration);
108
109 sp<AMessage> notify = mNotify->dup();
110 notify->setInt32("what", kWhatFillThisBuffer);
111 notify->setMessage("reply", reply);
112 notify->post();
113 mPendingBuffers++;
114
115 sp<AMessage> message = new AMessage(kWhatRequestABuffer, id());
116 message->setInt32("generation", mBufferGeneration);
117 message->post();
118 return;
119}
120
121void android::NuPlayer::DecoderPassThrough::onInputBufferFilled(
122 const sp<AMessage> &msg) {
123 if (mReachedEOS) {
124 return;
125 }
126
127 sp<ABuffer> buffer;
128 msg->findBuffer("buffer", &buffer);
129 if (buffer == NULL) {
130 mReachedEOS = true;
131
132 sp<AMessage> notify = mNotify->dup();
133 notify->setInt32("what", kWhatEOS);
134 notify->setInt32("err", ERROR_END_OF_STREAM);
135 notify->post();
136 return;
137 }
138
139 sp<AMessage> reply = new AMessage(kWhatBufferConsumed, id());
140 reply->setInt32("generation", mBufferGeneration);
141
142 sp<AMessage> notify = mNotify->dup();
143 notify->setInt32("what", kWhatDrainThisBuffer);
144 notify->setBuffer("buffer", buffer);
145 notify->setMessage("reply", reply);
146 notify->post();
147}
148
149void NuPlayer::DecoderPassThrough::onBufferConsumed() {
150 mPendingBuffers--;
151 sp<AMessage> message = new AMessage(kWhatRequestABuffer, id());
152 message->setInt32("generation", mBufferGeneration);
153 message->post();
154}
155
156void NuPlayer::DecoderPassThrough::onFlush() {
157 ++mBufferGeneration;
158
159 sp<AMessage> notify = mNotify->dup();
160 notify->setInt32("what", kWhatFlushCompleted);
161 notify->post();
162 mPendingBuffers = 0;
163 mReachedEOS = false;
164}
165
166void NuPlayer::DecoderPassThrough::onShutdown() {
167 ++mBufferGeneration;
168
169 sp<AMessage> notify = mNotify->dup();
170 notify->setInt32("what", kWhatShutdownCompleted);
171 notify->post();
172 mReachedEOS = true;
173}
174
175void NuPlayer::DecoderPassThrough::onMessageReceived(const sp<AMessage> &msg) {
176 ALOGV("[%s] onMessage: %s", mComponentName.c_str(),
177 msg->debugString().c_str());
178
179 switch (msg->what()) {
180 case kWhatConfigure:
181 {
182 sp<AMessage> format;
183 CHECK(msg->findMessage("format", &format));
184 onConfigure(format);
185 break;
186 }
187
188 case kWhatRequestABuffer:
189 {
190 if (!isStaleReply(msg)) {
191 requestABuffer();
192 }
193
194 break;
195 }
196
197 case kWhatInputBufferFilled:
198 {
199 if (!isStaleReply(msg)) {
200 onInputBufferFilled(msg);
201 }
202 break;
203 }
204
205 case kWhatBufferConsumed:
206 {
207 if (!isStaleReply(msg)) {
208 onBufferConsumed();
209 }
210 break;
211 }
212
213 case kWhatFlush:
214 {
215 onFlush();
216 break;
217 }
218
219 case kWhatResume:
220 {
221 requestABuffer();
222 break;
223 }
224
225 case kWhatShutdown:
226 {
227 onShutdown();
228 break;
229 }
230
231 default:
232 TRESPASS();
233 break;
234 }
235}
236
237} // namespace android