• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
31 namespace android {
32 
33 static const size_t kMaxCachedBytes = 200000;
34 // The buffers will contain a bit less than kAggregateBufferSizeBytes.
35 // So we can start off with just enough buffers to keep the cache full.
36 static const size_t kMaxPendingBuffers = 1 + (kMaxCachedBytes / NuPlayer::kAggregateBufferSizeBytes);
37 
DecoderPassThrough(const sp<AMessage> & notify)38 NuPlayer::DecoderPassThrough::DecoderPassThrough(
39         const sp<AMessage> &notify)
40     : Decoder(notify),
41       mNotify(notify),
42       mBufferGeneration(0),
43       mReachedEOS(true),
44       mPendingBuffersToFill(0),
45       mPendingBuffersToDrain(0),
46       mCachedBytes(0),
47       mComponentName("pass through decoder") {
48     mDecoderLooper = new ALooper;
49     mDecoderLooper->setName("NuPlayerDecoderPassThrough");
50     mDecoderLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
51 }
52 
~DecoderPassThrough()53 NuPlayer::DecoderPassThrough::~DecoderPassThrough() {
54 }
55 
configure(const sp<AMessage> & format)56 void NuPlayer::DecoderPassThrough::configure(const sp<AMessage> &format) {
57     sp<AMessage> msg = new AMessage(kWhatConfigure, id());
58     msg->setMessage("format", format);
59     msg->post();
60 }
61 
init()62 void NuPlayer::DecoderPassThrough::init() {
63     mDecoderLooper->registerHandler(this);
64 }
65 
signalFlush()66 void NuPlayer::DecoderPassThrough::signalFlush() {
67     (new AMessage(kWhatFlush, id()))->post();
68 }
69 
signalResume()70 void NuPlayer::DecoderPassThrough::signalResume() {
71     (new AMessage(kWhatResume, id()))->post();
72 }
73 
initiateShutdown()74 void NuPlayer::DecoderPassThrough::initiateShutdown() {
75     (new AMessage(kWhatShutdown, id()))->post();
76 }
77 
supportsSeamlessFormatChange(const sp<AMessage> &) const78 bool NuPlayer::DecoderPassThrough::supportsSeamlessFormatChange(
79         const sp<AMessage> & /* targetFormat */) const {
80     return true;
81 }
82 
onConfigure(const sp<AMessage> & format)83 void NuPlayer::DecoderPassThrough::onConfigure(const sp<AMessage> &format) {
84     ALOGV("[%s] onConfigure", mComponentName.c_str());
85     mCachedBytes = 0;
86     mPendingBuffersToFill = 0;
87     mPendingBuffersToDrain = 0;
88     mReachedEOS = false;
89     ++mBufferGeneration;
90 
91     requestMaxBuffers();
92 
93     sp<AMessage> notify = mNotify->dup();
94     notify->setInt32("what", kWhatOutputFormatChanged);
95     notify->setMessage("format", format);
96     notify->post();
97 }
98 
isStaleReply(const sp<AMessage> & msg)99 bool NuPlayer::DecoderPassThrough::isStaleReply(const sp<AMessage> &msg) {
100     int32_t generation;
101     CHECK(msg->findInt32("generation", &generation));
102     return generation != mBufferGeneration;
103 }
104 
requestABuffer()105 bool NuPlayer::DecoderPassThrough::requestABuffer() {
106     if (mCachedBytes >= kMaxCachedBytes) {
107         ALOGV("[%s] mCachedBytes = %zu",
108                 mComponentName.c_str(), mCachedBytes);
109         return false;
110     }
111     if (mReachedEOS) {
112         ALOGV("[%s] reached EOS", mComponentName.c_str());
113         return false;
114     }
115 
116     sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, id());
117     reply->setInt32("generation", mBufferGeneration);
118 
119     sp<AMessage> notify = mNotify->dup();
120     notify->setInt32("what", kWhatFillThisBuffer);
121     notify->setMessage("reply", reply);
122     notify->post();
123     mPendingBuffersToFill++;
124     ALOGV("requestABuffer: #ToFill = %zu, #ToDrain = %zu", mPendingBuffersToFill,
125             mPendingBuffersToDrain);
126 
127     return true;
128 }
129 
onInputBufferFilled(const sp<AMessage> & msg)130 void android::NuPlayer::DecoderPassThrough::onInputBufferFilled(
131         const sp<AMessage> &msg) {
132     --mPendingBuffersToFill;
133     if (mReachedEOS) {
134         return;
135     }
136 
137     sp<ABuffer> buffer;
138     msg->findBuffer("buffer", &buffer);
139     if (buffer == NULL) {
140         mReachedEOS = true;
141 
142         sp<AMessage> notify = mNotify->dup();
143         notify->setInt32("what", kWhatEOS);
144         notify->setInt32("err", ERROR_END_OF_STREAM);
145         notify->post();
146         return;
147     }
148 
149     mCachedBytes += buffer->size();
150 
151     sp<AMessage> reply = new AMessage(kWhatBufferConsumed, id());
152     reply->setInt32("generation", mBufferGeneration);
153     reply->setInt32("size", buffer->size());
154 
155     sp<AMessage> notify = mNotify->dup();
156     notify->setInt32("what", kWhatDrainThisBuffer);
157     notify->setBuffer("buffer", buffer);
158     notify->setMessage("reply", reply);
159     notify->post();
160     ++mPendingBuffersToDrain;
161     ALOGV("onInputBufferFilled: #ToFill = %zu, #ToDrain = %zu, cachedBytes = %zu",
162             mPendingBuffersToFill, mPendingBuffersToDrain, mCachedBytes);
163 }
164 
onBufferConsumed(int32_t size)165 void NuPlayer::DecoderPassThrough::onBufferConsumed(int32_t size) {
166     --mPendingBuffersToDrain;
167     mCachedBytes -= size;
168     ALOGV("onBufferConsumed: #ToFill = %zu, #ToDrain = %zu, cachedBytes = %zu",
169            mPendingBuffersToFill, mPendingBuffersToDrain, mCachedBytes);
170     requestABuffer();
171 }
172 
onFlush()173 void NuPlayer::DecoderPassThrough::onFlush() {
174     ++mBufferGeneration;
175 
176     sp<AMessage> notify = mNotify->dup();
177     notify->setInt32("what", kWhatFlushCompleted);
178     notify->post();
179     mPendingBuffersToFill = 0;
180     mPendingBuffersToDrain = 0;
181     mCachedBytes = 0;
182     mReachedEOS = false;
183 }
184 
requestMaxBuffers()185 void NuPlayer::DecoderPassThrough::requestMaxBuffers() {
186     for (size_t i = 0; i < kMaxPendingBuffers; i++) {
187         if (!requestABuffer()) {
188             break;
189         }
190     }
191 }
192 
onShutdown()193 void NuPlayer::DecoderPassThrough::onShutdown() {
194     ++mBufferGeneration;
195 
196     sp<AMessage> notify = mNotify->dup();
197     notify->setInt32("what", kWhatShutdownCompleted);
198     notify->post();
199     mReachedEOS = true;
200 }
201 
onMessageReceived(const sp<AMessage> & msg)202 void NuPlayer::DecoderPassThrough::onMessageReceived(const sp<AMessage> &msg) {
203     ALOGV("[%s] onMessage: %s", mComponentName.c_str(),
204             msg->debugString().c_str());
205 
206     switch (msg->what()) {
207         case kWhatConfigure:
208         {
209             sp<AMessage> format;
210             CHECK(msg->findMessage("format", &format));
211             onConfigure(format);
212             break;
213         }
214 
215         case kWhatRequestABuffer:
216         {
217             if (!isStaleReply(msg)) {
218                 requestABuffer();
219             }
220 
221             break;
222         }
223 
224         case kWhatInputBufferFilled:
225         {
226             if (!isStaleReply(msg)) {
227                 onInputBufferFilled(msg);
228             }
229             break;
230         }
231 
232         case kWhatBufferConsumed:
233         {
234             if (!isStaleReply(msg)) {
235                 int32_t size;
236                 CHECK(msg->findInt32("size", &size));
237                 onBufferConsumed(size);
238             }
239             break;
240         }
241 
242         case kWhatFlush:
243         {
244             onFlush();
245             break;
246         }
247 
248         case kWhatResume:
249         {
250             requestMaxBuffers();
251             break;
252         }
253 
254         case kWhatShutdown:
255         {
256             onShutdown();
257             break;
258         }
259 
260         default:
261             TRESPASS();
262             break;
263     }
264 }
265 
266 }  // namespace android
267