1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker
17*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "NuPlayerDecoderPassThrough"
19*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
20*ec779b8eSAndroid Build Coastguard Worker #include <inttypes.h>
21*ec779b8eSAndroid Build Coastguard Worker
22*ec779b8eSAndroid Build Coastguard Worker #include "NuPlayerDecoderPassThrough.h"
23*ec779b8eSAndroid Build Coastguard Worker
24*ec779b8eSAndroid Build Coastguard Worker #include "NuPlayerRenderer.h"
25*ec779b8eSAndroid Build Coastguard Worker #include "NuPlayerSource.h"
26*ec779b8eSAndroid Build Coastguard Worker
27*ec779b8eSAndroid Build Coastguard Worker #include <mediadrm/ICrypto.h>
28*ec779b8eSAndroid Build Coastguard Worker #include <media/MediaCodecBuffer.h>
29*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ABuffer.h>
30*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ADebug.h>
31*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/AMessage.h>
32*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaErrors.h>
33*ec779b8eSAndroid Build Coastguard Worker #include <mpeg2ts/ATSParser.h>
34*ec779b8eSAndroid Build Coastguard Worker
35*ec779b8eSAndroid Build Coastguard Worker namespace android {
36*ec779b8eSAndroid Build Coastguard Worker
37*ec779b8eSAndroid Build Coastguard Worker // TODO optimize buffer size for power consumption
38*ec779b8eSAndroid Build Coastguard Worker // The offload read buffer size is 32 KB but 24 KB uses less power.
39*ec779b8eSAndroid Build Coastguard Worker static const size_t kAggregateBufferSizeBytes = 24 * 1024;
40*ec779b8eSAndroid Build Coastguard Worker static const size_t kMaxCachedBytes = 200000;
41*ec779b8eSAndroid Build Coastguard Worker
DecoderPassThrough(const sp<AMessage> & notify,const sp<Source> & source,const sp<Renderer> & renderer)42*ec779b8eSAndroid Build Coastguard Worker NuPlayer::DecoderPassThrough::DecoderPassThrough(
43*ec779b8eSAndroid Build Coastguard Worker const sp<AMessage> ¬ify,
44*ec779b8eSAndroid Build Coastguard Worker const sp<Source> &source,
45*ec779b8eSAndroid Build Coastguard Worker const sp<Renderer> &renderer)
46*ec779b8eSAndroid Build Coastguard Worker : DecoderBase(notify),
47*ec779b8eSAndroid Build Coastguard Worker mSource(source),
48*ec779b8eSAndroid Build Coastguard Worker mRenderer(renderer),
49*ec779b8eSAndroid Build Coastguard Worker mSkipRenderingUntilMediaTimeUs(-1LL),
50*ec779b8eSAndroid Build Coastguard Worker mReachedEOS(true),
51*ec779b8eSAndroid Build Coastguard Worker mPendingAudioErr(OK),
52*ec779b8eSAndroid Build Coastguard Worker mPendingBuffersToDrain(0),
53*ec779b8eSAndroid Build Coastguard Worker mCachedBytes(0),
54*ec779b8eSAndroid Build Coastguard Worker mComponentName("pass through decoder") {
55*ec779b8eSAndroid Build Coastguard Worker ALOGW_IF(renderer == NULL, "expect a non-NULL renderer");
56*ec779b8eSAndroid Build Coastguard Worker }
57*ec779b8eSAndroid Build Coastguard Worker
~DecoderPassThrough()58*ec779b8eSAndroid Build Coastguard Worker NuPlayer::DecoderPassThrough::~DecoderPassThrough() {
59*ec779b8eSAndroid Build Coastguard Worker }
60*ec779b8eSAndroid Build Coastguard Worker
onConfigure(const sp<AMessage> & format)61*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::DecoderPassThrough::onConfigure(const sp<AMessage> &format) {
62*ec779b8eSAndroid Build Coastguard Worker ALOGV("[%s] onConfigure", mComponentName.c_str());
63*ec779b8eSAndroid Build Coastguard Worker mCachedBytes = 0;
64*ec779b8eSAndroid Build Coastguard Worker mPendingBuffersToDrain = 0;
65*ec779b8eSAndroid Build Coastguard Worker mReachedEOS = false;
66*ec779b8eSAndroid Build Coastguard Worker ++mBufferGeneration;
67*ec779b8eSAndroid Build Coastguard Worker
68*ec779b8eSAndroid Build Coastguard Worker onRequestInputBuffers();
69*ec779b8eSAndroid Build Coastguard Worker
70*ec779b8eSAndroid Build Coastguard Worker int32_t hasVideo = 0;
71*ec779b8eSAndroid Build Coastguard Worker format->findInt32("has-video", &hasVideo);
72*ec779b8eSAndroid Build Coastguard Worker
73*ec779b8eSAndroid Build Coastguard Worker // The audio sink is already opened before the PassThrough decoder is created.
74*ec779b8eSAndroid Build Coastguard Worker // Opening again might be relevant if decoder is instantiated after shutdown and
75*ec779b8eSAndroid Build Coastguard Worker // format is different.
76*ec779b8eSAndroid Build Coastguard Worker status_t err = mRenderer->openAudioSink(
77*ec779b8eSAndroid Build Coastguard Worker format, true /* offloadOnly */, hasVideo,
78*ec779b8eSAndroid Build Coastguard Worker AUDIO_OUTPUT_FLAG_NONE /* flags */, NULL /* isOffloaded */, mSource->isStreaming());
79*ec779b8eSAndroid Build Coastguard Worker if (err != OK) {
80*ec779b8eSAndroid Build Coastguard Worker handleError(err);
81*ec779b8eSAndroid Build Coastguard Worker }
82*ec779b8eSAndroid Build Coastguard Worker }
83*ec779b8eSAndroid Build Coastguard Worker
onSetParameters(const sp<AMessage> &)84*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::DecoderPassThrough::onSetParameters(const sp<AMessage> &/*params*/) {
85*ec779b8eSAndroid Build Coastguard Worker ALOGW("onSetParameters() called unexpectedly");
86*ec779b8eSAndroid Build Coastguard Worker }
87*ec779b8eSAndroid Build Coastguard Worker
onSetRenderer(const sp<Renderer> & renderer)88*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::DecoderPassThrough::onSetRenderer(
89*ec779b8eSAndroid Build Coastguard Worker const sp<Renderer> &renderer) {
90*ec779b8eSAndroid Build Coastguard Worker // renderer can't be changed during offloading
91*ec779b8eSAndroid Build Coastguard Worker ALOGW_IF(renderer != mRenderer,
92*ec779b8eSAndroid Build Coastguard Worker "ignoring request to change renderer");
93*ec779b8eSAndroid Build Coastguard Worker }
94*ec779b8eSAndroid Build Coastguard Worker
isStaleReply(const sp<AMessage> & msg)95*ec779b8eSAndroid Build Coastguard Worker bool NuPlayer::DecoderPassThrough::isStaleReply(const sp<AMessage> &msg) {
96*ec779b8eSAndroid Build Coastguard Worker int32_t generation;
97*ec779b8eSAndroid Build Coastguard Worker CHECK(msg->findInt32("generation", &generation));
98*ec779b8eSAndroid Build Coastguard Worker return generation != mBufferGeneration;
99*ec779b8eSAndroid Build Coastguard Worker }
100*ec779b8eSAndroid Build Coastguard Worker
isDoneFetching() const101*ec779b8eSAndroid Build Coastguard Worker bool NuPlayer::DecoderPassThrough::isDoneFetching() const {
102*ec779b8eSAndroid Build Coastguard Worker ALOGV("[%s] mCachedBytes = %zu, mReachedEOS = %d mPaused = %d",
103*ec779b8eSAndroid Build Coastguard Worker mComponentName.c_str(), mCachedBytes, mReachedEOS, mPaused);
104*ec779b8eSAndroid Build Coastguard Worker
105*ec779b8eSAndroid Build Coastguard Worker return mCachedBytes >= kMaxCachedBytes || mReachedEOS || mPaused;
106*ec779b8eSAndroid Build Coastguard Worker }
107*ec779b8eSAndroid Build Coastguard Worker
108*ec779b8eSAndroid Build Coastguard Worker /*
109*ec779b8eSAndroid Build Coastguard Worker * returns true if we should request more data
110*ec779b8eSAndroid Build Coastguard Worker */
doRequestBuffers()111*ec779b8eSAndroid Build Coastguard Worker bool NuPlayer::DecoderPassThrough::doRequestBuffers() {
112*ec779b8eSAndroid Build Coastguard Worker status_t err = OK;
113*ec779b8eSAndroid Build Coastguard Worker while (!isDoneFetching()) {
114*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> msg = new AMessage();
115*ec779b8eSAndroid Build Coastguard Worker
116*ec779b8eSAndroid Build Coastguard Worker err = fetchInputData(msg);
117*ec779b8eSAndroid Build Coastguard Worker if (err != OK) {
118*ec779b8eSAndroid Build Coastguard Worker break;
119*ec779b8eSAndroid Build Coastguard Worker }
120*ec779b8eSAndroid Build Coastguard Worker
121*ec779b8eSAndroid Build Coastguard Worker onInputBufferFetched(msg);
122*ec779b8eSAndroid Build Coastguard Worker }
123*ec779b8eSAndroid Build Coastguard Worker
124*ec779b8eSAndroid Build Coastguard Worker return err == -EWOULDBLOCK
125*ec779b8eSAndroid Build Coastguard Worker && mSource->feedMoreTSData() == OK;
126*ec779b8eSAndroid Build Coastguard Worker }
127*ec779b8eSAndroid Build Coastguard Worker
dequeueAccessUnit(sp<ABuffer> * accessUnit)128*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::DecoderPassThrough::dequeueAccessUnit(sp<ABuffer> *accessUnit) {
129*ec779b8eSAndroid Build Coastguard Worker status_t err;
130*ec779b8eSAndroid Build Coastguard Worker
131*ec779b8eSAndroid Build Coastguard Worker // Did we save an accessUnit earlier because of a discontinuity?
132*ec779b8eSAndroid Build Coastguard Worker if (mPendingAudioAccessUnit != NULL) {
133*ec779b8eSAndroid Build Coastguard Worker *accessUnit = mPendingAudioAccessUnit;
134*ec779b8eSAndroid Build Coastguard Worker mPendingAudioAccessUnit.clear();
135*ec779b8eSAndroid Build Coastguard Worker err = mPendingAudioErr;
136*ec779b8eSAndroid Build Coastguard Worker ALOGV("feedDecoderInputData() use mPendingAudioAccessUnit");
137*ec779b8eSAndroid Build Coastguard Worker } else {
138*ec779b8eSAndroid Build Coastguard Worker err = mSource->dequeueAccessUnit(true /* audio */, accessUnit);
139*ec779b8eSAndroid Build Coastguard Worker }
140*ec779b8eSAndroid Build Coastguard Worker
141*ec779b8eSAndroid Build Coastguard Worker if (err == INFO_DISCONTINUITY || err == ERROR_END_OF_STREAM) {
142*ec779b8eSAndroid Build Coastguard Worker if (mAggregateBuffer != NULL) {
143*ec779b8eSAndroid Build Coastguard Worker // We already have some data so save this for later.
144*ec779b8eSAndroid Build Coastguard Worker mPendingAudioErr = err;
145*ec779b8eSAndroid Build Coastguard Worker mPendingAudioAccessUnit = *accessUnit;
146*ec779b8eSAndroid Build Coastguard Worker (*accessUnit).clear();
147*ec779b8eSAndroid Build Coastguard Worker ALOGD("return aggregated buffer and save err(=%d) for later", err);
148*ec779b8eSAndroid Build Coastguard Worker err = OK;
149*ec779b8eSAndroid Build Coastguard Worker }
150*ec779b8eSAndroid Build Coastguard Worker }
151*ec779b8eSAndroid Build Coastguard Worker
152*ec779b8eSAndroid Build Coastguard Worker return err;
153*ec779b8eSAndroid Build Coastguard Worker }
154*ec779b8eSAndroid Build Coastguard Worker
aggregateBuffer(const sp<ABuffer> & accessUnit)155*ec779b8eSAndroid Build Coastguard Worker sp<ABuffer> NuPlayer::DecoderPassThrough::aggregateBuffer(
156*ec779b8eSAndroid Build Coastguard Worker const sp<ABuffer> &accessUnit) {
157*ec779b8eSAndroid Build Coastguard Worker sp<ABuffer> aggregate;
158*ec779b8eSAndroid Build Coastguard Worker
159*ec779b8eSAndroid Build Coastguard Worker if (accessUnit == NULL) {
160*ec779b8eSAndroid Build Coastguard Worker // accessUnit is saved to mPendingAudioAccessUnit
161*ec779b8eSAndroid Build Coastguard Worker // return current mAggregateBuffer
162*ec779b8eSAndroid Build Coastguard Worker aggregate = mAggregateBuffer;
163*ec779b8eSAndroid Build Coastguard Worker mAggregateBuffer.clear();
164*ec779b8eSAndroid Build Coastguard Worker return aggregate;
165*ec779b8eSAndroid Build Coastguard Worker }
166*ec779b8eSAndroid Build Coastguard Worker
167*ec779b8eSAndroid Build Coastguard Worker size_t smallSize = accessUnit->size();
168*ec779b8eSAndroid Build Coastguard Worker if ((mAggregateBuffer == NULL)
169*ec779b8eSAndroid Build Coastguard Worker // Don't bother if only room for a few small buffers.
170*ec779b8eSAndroid Build Coastguard Worker && (smallSize < (kAggregateBufferSizeBytes / 3))) {
171*ec779b8eSAndroid Build Coastguard Worker // Create a larger buffer for combining smaller buffers from the extractor.
172*ec779b8eSAndroid Build Coastguard Worker mAggregateBuffer = new ABuffer(kAggregateBufferSizeBytes);
173*ec779b8eSAndroid Build Coastguard Worker mAggregateBuffer->setRange(0, 0); // start empty
174*ec779b8eSAndroid Build Coastguard Worker }
175*ec779b8eSAndroid Build Coastguard Worker
176*ec779b8eSAndroid Build Coastguard Worker if (mAggregateBuffer != NULL) {
177*ec779b8eSAndroid Build Coastguard Worker int64_t timeUs;
178*ec779b8eSAndroid Build Coastguard Worker int64_t dummy;
179*ec779b8eSAndroid Build Coastguard Worker bool smallTimestampValid = accessUnit->meta()->findInt64("timeUs", &timeUs);
180*ec779b8eSAndroid Build Coastguard Worker bool bigTimestampValid = mAggregateBuffer->meta()->findInt64("timeUs", &dummy);
181*ec779b8eSAndroid Build Coastguard Worker // Will the smaller buffer fit?
182*ec779b8eSAndroid Build Coastguard Worker size_t bigSize = mAggregateBuffer->size();
183*ec779b8eSAndroid Build Coastguard Worker size_t roomLeft = mAggregateBuffer->capacity() - bigSize;
184*ec779b8eSAndroid Build Coastguard Worker // Should we save this small buffer for the next big buffer?
185*ec779b8eSAndroid Build Coastguard Worker // If the first small buffer did not have a timestamp then save
186*ec779b8eSAndroid Build Coastguard Worker // any buffer that does have a timestamp until the next big buffer.
187*ec779b8eSAndroid Build Coastguard Worker if ((smallSize > roomLeft)
188*ec779b8eSAndroid Build Coastguard Worker || (!bigTimestampValid && (bigSize > 0) && smallTimestampValid)) {
189*ec779b8eSAndroid Build Coastguard Worker mPendingAudioErr = OK;
190*ec779b8eSAndroid Build Coastguard Worker mPendingAudioAccessUnit = accessUnit;
191*ec779b8eSAndroid Build Coastguard Worker aggregate = mAggregateBuffer;
192*ec779b8eSAndroid Build Coastguard Worker mAggregateBuffer.clear();
193*ec779b8eSAndroid Build Coastguard Worker } else {
194*ec779b8eSAndroid Build Coastguard Worker // Grab time from first small buffer if available.
195*ec779b8eSAndroid Build Coastguard Worker if ((bigSize == 0) && smallTimestampValid) {
196*ec779b8eSAndroid Build Coastguard Worker mAggregateBuffer->meta()->setInt64("timeUs", timeUs);
197*ec779b8eSAndroid Build Coastguard Worker }
198*ec779b8eSAndroid Build Coastguard Worker // Append small buffer to the bigger buffer.
199*ec779b8eSAndroid Build Coastguard Worker memcpy(mAggregateBuffer->base() + bigSize, accessUnit->data(), smallSize);
200*ec779b8eSAndroid Build Coastguard Worker bigSize += smallSize;
201*ec779b8eSAndroid Build Coastguard Worker mAggregateBuffer->setRange(0, bigSize);
202*ec779b8eSAndroid Build Coastguard Worker
203*ec779b8eSAndroid Build Coastguard Worker ALOGV("feedDecoderInputData() smallSize = %zu, bigSize = %zu, capacity = %zu",
204*ec779b8eSAndroid Build Coastguard Worker smallSize, bigSize, mAggregateBuffer->capacity());
205*ec779b8eSAndroid Build Coastguard Worker }
206*ec779b8eSAndroid Build Coastguard Worker } else {
207*ec779b8eSAndroid Build Coastguard Worker // decided not to aggregate
208*ec779b8eSAndroid Build Coastguard Worker aggregate = accessUnit;
209*ec779b8eSAndroid Build Coastguard Worker }
210*ec779b8eSAndroid Build Coastguard Worker
211*ec779b8eSAndroid Build Coastguard Worker return aggregate;
212*ec779b8eSAndroid Build Coastguard Worker }
213*ec779b8eSAndroid Build Coastguard Worker
fetchInputData(sp<AMessage> & reply)214*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::DecoderPassThrough::fetchInputData(sp<AMessage> &reply) {
215*ec779b8eSAndroid Build Coastguard Worker sp<ABuffer> accessUnit;
216*ec779b8eSAndroid Build Coastguard Worker
217*ec779b8eSAndroid Build Coastguard Worker do {
218*ec779b8eSAndroid Build Coastguard Worker status_t err = dequeueAccessUnit(&accessUnit);
219*ec779b8eSAndroid Build Coastguard Worker
220*ec779b8eSAndroid Build Coastguard Worker if (err == -EWOULDBLOCK) {
221*ec779b8eSAndroid Build Coastguard Worker // Flush out the aggregate buffer to try to avoid underrun.
222*ec779b8eSAndroid Build Coastguard Worker accessUnit = aggregateBuffer(NULL /* accessUnit */);
223*ec779b8eSAndroid Build Coastguard Worker if (accessUnit != NULL) {
224*ec779b8eSAndroid Build Coastguard Worker break;
225*ec779b8eSAndroid Build Coastguard Worker }
226*ec779b8eSAndroid Build Coastguard Worker return err;
227*ec779b8eSAndroid Build Coastguard Worker } else if (err != OK) {
228*ec779b8eSAndroid Build Coastguard Worker if (err == INFO_DISCONTINUITY) {
229*ec779b8eSAndroid Build Coastguard Worker int32_t type;
230*ec779b8eSAndroid Build Coastguard Worker CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
231*ec779b8eSAndroid Build Coastguard Worker
232*ec779b8eSAndroid Build Coastguard Worker bool formatChange =
233*ec779b8eSAndroid Build Coastguard Worker (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT) != 0;
234*ec779b8eSAndroid Build Coastguard Worker
235*ec779b8eSAndroid Build Coastguard Worker bool timeChange =
236*ec779b8eSAndroid Build Coastguard Worker (type & ATSParser::DISCONTINUITY_TIME) != 0;
237*ec779b8eSAndroid Build Coastguard Worker
238*ec779b8eSAndroid Build Coastguard Worker ALOGI("audio discontinuity (formatChange=%d, time=%d)",
239*ec779b8eSAndroid Build Coastguard Worker formatChange, timeChange);
240*ec779b8eSAndroid Build Coastguard Worker
241*ec779b8eSAndroid Build Coastguard Worker if (formatChange || timeChange) {
242*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> msg = mNotify->dup();
243*ec779b8eSAndroid Build Coastguard Worker msg->setInt32("what", kWhatInputDiscontinuity);
244*ec779b8eSAndroid Build Coastguard Worker // will perform seamless format change,
245*ec779b8eSAndroid Build Coastguard Worker // only notify NuPlayer to scan sources
246*ec779b8eSAndroid Build Coastguard Worker msg->setInt32("formatChange", false);
247*ec779b8eSAndroid Build Coastguard Worker msg->post();
248*ec779b8eSAndroid Build Coastguard Worker }
249*ec779b8eSAndroid Build Coastguard Worker
250*ec779b8eSAndroid Build Coastguard Worker if (timeChange) {
251*ec779b8eSAndroid Build Coastguard Worker doFlush(false /* notifyComplete */);
252*ec779b8eSAndroid Build Coastguard Worker err = OK;
253*ec779b8eSAndroid Build Coastguard Worker } else if (formatChange) {
254*ec779b8eSAndroid Build Coastguard Worker // do seamless format change
255*ec779b8eSAndroid Build Coastguard Worker err = OK;
256*ec779b8eSAndroid Build Coastguard Worker } else {
257*ec779b8eSAndroid Build Coastguard Worker // This stream is unaffected by the discontinuity
258*ec779b8eSAndroid Build Coastguard Worker return -EWOULDBLOCK;
259*ec779b8eSAndroid Build Coastguard Worker }
260*ec779b8eSAndroid Build Coastguard Worker }
261*ec779b8eSAndroid Build Coastguard Worker
262*ec779b8eSAndroid Build Coastguard Worker reply->setInt32("err", err);
263*ec779b8eSAndroid Build Coastguard Worker return OK;
264*ec779b8eSAndroid Build Coastguard Worker }
265*ec779b8eSAndroid Build Coastguard Worker
266*ec779b8eSAndroid Build Coastguard Worker accessUnit = aggregateBuffer(accessUnit);
267*ec779b8eSAndroid Build Coastguard Worker } while (accessUnit == NULL);
268*ec779b8eSAndroid Build Coastguard Worker
269*ec779b8eSAndroid Build Coastguard Worker #if 0
270*ec779b8eSAndroid Build Coastguard Worker int64_t mediaTimeUs;
271*ec779b8eSAndroid Build Coastguard Worker CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
272*ec779b8eSAndroid Build Coastguard Worker ALOGV("feeding audio input buffer at media time %.2f secs",
273*ec779b8eSAndroid Build Coastguard Worker mediaTimeUs / 1E6);
274*ec779b8eSAndroid Build Coastguard Worker #endif
275*ec779b8eSAndroid Build Coastguard Worker
276*ec779b8eSAndroid Build Coastguard Worker reply->setBuffer("buffer", accessUnit);
277*ec779b8eSAndroid Build Coastguard Worker
278*ec779b8eSAndroid Build Coastguard Worker return OK;
279*ec779b8eSAndroid Build Coastguard Worker }
280*ec779b8eSAndroid Build Coastguard Worker
onInputBufferFetched(const sp<AMessage> & msg)281*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::DecoderPassThrough::onInputBufferFetched(
282*ec779b8eSAndroid Build Coastguard Worker const sp<AMessage> &msg) {
283*ec779b8eSAndroid Build Coastguard Worker if (mReachedEOS) {
284*ec779b8eSAndroid Build Coastguard Worker return;
285*ec779b8eSAndroid Build Coastguard Worker }
286*ec779b8eSAndroid Build Coastguard Worker
287*ec779b8eSAndroid Build Coastguard Worker sp<ABuffer> buffer;
288*ec779b8eSAndroid Build Coastguard Worker bool hasBuffer = msg->findBuffer("buffer", &buffer);
289*ec779b8eSAndroid Build Coastguard Worker if (buffer == NULL) {
290*ec779b8eSAndroid Build Coastguard Worker int32_t streamErr = ERROR_END_OF_STREAM;
291*ec779b8eSAndroid Build Coastguard Worker CHECK(msg->findInt32("err", &streamErr) || !hasBuffer);
292*ec779b8eSAndroid Build Coastguard Worker if (streamErr == OK) {
293*ec779b8eSAndroid Build Coastguard Worker return;
294*ec779b8eSAndroid Build Coastguard Worker }
295*ec779b8eSAndroid Build Coastguard Worker
296*ec779b8eSAndroid Build Coastguard Worker if (streamErr != ERROR_END_OF_STREAM) {
297*ec779b8eSAndroid Build Coastguard Worker handleError(streamErr);
298*ec779b8eSAndroid Build Coastguard Worker }
299*ec779b8eSAndroid Build Coastguard Worker mReachedEOS = true;
300*ec779b8eSAndroid Build Coastguard Worker if (mRenderer != NULL) {
301*ec779b8eSAndroid Build Coastguard Worker mRenderer->queueEOS(true /* audio */, ERROR_END_OF_STREAM);
302*ec779b8eSAndroid Build Coastguard Worker }
303*ec779b8eSAndroid Build Coastguard Worker return;
304*ec779b8eSAndroid Build Coastguard Worker }
305*ec779b8eSAndroid Build Coastguard Worker
306*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> extra;
307*ec779b8eSAndroid Build Coastguard Worker if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) {
308*ec779b8eSAndroid Build Coastguard Worker int64_t resumeAtMediaTimeUs;
309*ec779b8eSAndroid Build Coastguard Worker if (extra->findInt64(
310*ec779b8eSAndroid Build Coastguard Worker "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
311*ec779b8eSAndroid Build Coastguard Worker ALOGI("[%s] suppressing rendering until %lld us",
312*ec779b8eSAndroid Build Coastguard Worker mComponentName.c_str(), (long long)resumeAtMediaTimeUs);
313*ec779b8eSAndroid Build Coastguard Worker mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs;
314*ec779b8eSAndroid Build Coastguard Worker }
315*ec779b8eSAndroid Build Coastguard Worker }
316*ec779b8eSAndroid Build Coastguard Worker
317*ec779b8eSAndroid Build Coastguard Worker int32_t bufferSize = buffer->size();
318*ec779b8eSAndroid Build Coastguard Worker mCachedBytes += bufferSize;
319*ec779b8eSAndroid Build Coastguard Worker
320*ec779b8eSAndroid Build Coastguard Worker int64_t timeUs = 0;
321*ec779b8eSAndroid Build Coastguard Worker CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
322*ec779b8eSAndroid Build Coastguard Worker if (mSkipRenderingUntilMediaTimeUs >= 0) {
323*ec779b8eSAndroid Build Coastguard Worker if (timeUs < mSkipRenderingUntilMediaTimeUs) {
324*ec779b8eSAndroid Build Coastguard Worker ALOGV("[%s] dropping buffer at time %lld as requested.",
325*ec779b8eSAndroid Build Coastguard Worker mComponentName.c_str(), (long long)timeUs);
326*ec779b8eSAndroid Build Coastguard Worker
327*ec779b8eSAndroid Build Coastguard Worker onBufferConsumed(bufferSize);
328*ec779b8eSAndroid Build Coastguard Worker return;
329*ec779b8eSAndroid Build Coastguard Worker }
330*ec779b8eSAndroid Build Coastguard Worker
331*ec779b8eSAndroid Build Coastguard Worker mSkipRenderingUntilMediaTimeUs = -1;
332*ec779b8eSAndroid Build Coastguard Worker }
333*ec779b8eSAndroid Build Coastguard Worker
334*ec779b8eSAndroid Build Coastguard Worker if (mRenderer == NULL) {
335*ec779b8eSAndroid Build Coastguard Worker onBufferConsumed(bufferSize);
336*ec779b8eSAndroid Build Coastguard Worker return;
337*ec779b8eSAndroid Build Coastguard Worker }
338*ec779b8eSAndroid Build Coastguard Worker
339*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> reply = new AMessage(kWhatBufferConsumed, this);
340*ec779b8eSAndroid Build Coastguard Worker reply->setInt32("generation", mBufferGeneration);
341*ec779b8eSAndroid Build Coastguard Worker reply->setInt32("size", bufferSize);
342*ec779b8eSAndroid Build Coastguard Worker
343*ec779b8eSAndroid Build Coastguard Worker sp<MediaCodecBuffer> mcBuffer = new MediaCodecBuffer(nullptr, buffer);
344*ec779b8eSAndroid Build Coastguard Worker mcBuffer->meta()->setInt64("timeUs", timeUs);
345*ec779b8eSAndroid Build Coastguard Worker
346*ec779b8eSAndroid Build Coastguard Worker mRenderer->queueBuffer(true /* audio */, mcBuffer, reply);
347*ec779b8eSAndroid Build Coastguard Worker
348*ec779b8eSAndroid Build Coastguard Worker ++mPendingBuffersToDrain;
349*ec779b8eSAndroid Build Coastguard Worker ALOGV("onInputBufferFilled: #ToDrain = %zu, cachedBytes = %zu",
350*ec779b8eSAndroid Build Coastguard Worker mPendingBuffersToDrain, mCachedBytes);
351*ec779b8eSAndroid Build Coastguard Worker }
352*ec779b8eSAndroid Build Coastguard Worker
onBufferConsumed(int32_t size)353*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::DecoderPassThrough::onBufferConsumed(int32_t size) {
354*ec779b8eSAndroid Build Coastguard Worker --mPendingBuffersToDrain;
355*ec779b8eSAndroid Build Coastguard Worker mCachedBytes -= size;
356*ec779b8eSAndroid Build Coastguard Worker ALOGV("onBufferConsumed: #ToDrain = %zu, cachedBytes = %zu",
357*ec779b8eSAndroid Build Coastguard Worker mPendingBuffersToDrain, mCachedBytes);
358*ec779b8eSAndroid Build Coastguard Worker onRequestInputBuffers();
359*ec779b8eSAndroid Build Coastguard Worker }
360*ec779b8eSAndroid Build Coastguard Worker
onResume(bool notifyComplete)361*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::DecoderPassThrough::onResume(bool notifyComplete) {
362*ec779b8eSAndroid Build Coastguard Worker mPaused = false;
363*ec779b8eSAndroid Build Coastguard Worker
364*ec779b8eSAndroid Build Coastguard Worker onRequestInputBuffers();
365*ec779b8eSAndroid Build Coastguard Worker
366*ec779b8eSAndroid Build Coastguard Worker if (notifyComplete) {
367*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> notify = mNotify->dup();
368*ec779b8eSAndroid Build Coastguard Worker notify->setInt32("what", kWhatResumeCompleted);
369*ec779b8eSAndroid Build Coastguard Worker notify->post();
370*ec779b8eSAndroid Build Coastguard Worker }
371*ec779b8eSAndroid Build Coastguard Worker }
372*ec779b8eSAndroid Build Coastguard Worker
doFlush(bool notifyComplete)373*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::DecoderPassThrough::doFlush(bool notifyComplete) {
374*ec779b8eSAndroid Build Coastguard Worker ++mBufferGeneration;
375*ec779b8eSAndroid Build Coastguard Worker mSkipRenderingUntilMediaTimeUs = -1;
376*ec779b8eSAndroid Build Coastguard Worker mPendingAudioAccessUnit.clear();
377*ec779b8eSAndroid Build Coastguard Worker mPendingAudioErr = OK;
378*ec779b8eSAndroid Build Coastguard Worker mAggregateBuffer.clear();
379*ec779b8eSAndroid Build Coastguard Worker
380*ec779b8eSAndroid Build Coastguard Worker if (mRenderer != NULL) {
381*ec779b8eSAndroid Build Coastguard Worker mRenderer->flush(true /* audio */, notifyComplete);
382*ec779b8eSAndroid Build Coastguard Worker mRenderer->signalTimeDiscontinuity();
383*ec779b8eSAndroid Build Coastguard Worker }
384*ec779b8eSAndroid Build Coastguard Worker
385*ec779b8eSAndroid Build Coastguard Worker mPendingBuffersToDrain = 0;
386*ec779b8eSAndroid Build Coastguard Worker mCachedBytes = 0;
387*ec779b8eSAndroid Build Coastguard Worker mReachedEOS = false;
388*ec779b8eSAndroid Build Coastguard Worker }
389*ec779b8eSAndroid Build Coastguard Worker
onFlush()390*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::DecoderPassThrough::onFlush() {
391*ec779b8eSAndroid Build Coastguard Worker doFlush(true /* notifyComplete */);
392*ec779b8eSAndroid Build Coastguard Worker
393*ec779b8eSAndroid Build Coastguard Worker mPaused = true;
394*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> notify = mNotify->dup();
395*ec779b8eSAndroid Build Coastguard Worker notify->setInt32("what", kWhatFlushCompleted);
396*ec779b8eSAndroid Build Coastguard Worker notify->post();
397*ec779b8eSAndroid Build Coastguard Worker
398*ec779b8eSAndroid Build Coastguard Worker }
399*ec779b8eSAndroid Build Coastguard Worker
onShutdown(bool notifyComplete)400*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::DecoderPassThrough::onShutdown(bool notifyComplete) {
401*ec779b8eSAndroid Build Coastguard Worker ++mBufferGeneration;
402*ec779b8eSAndroid Build Coastguard Worker mSkipRenderingUntilMediaTimeUs = -1;
403*ec779b8eSAndroid Build Coastguard Worker
404*ec779b8eSAndroid Build Coastguard Worker if (notifyComplete) {
405*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> notify = mNotify->dup();
406*ec779b8eSAndroid Build Coastguard Worker notify->setInt32("what", kWhatShutdownCompleted);
407*ec779b8eSAndroid Build Coastguard Worker notify->post();
408*ec779b8eSAndroid Build Coastguard Worker }
409*ec779b8eSAndroid Build Coastguard Worker
410*ec779b8eSAndroid Build Coastguard Worker mReachedEOS = true;
411*ec779b8eSAndroid Build Coastguard Worker }
412*ec779b8eSAndroid Build Coastguard Worker
onMessageReceived(const sp<AMessage> & msg)413*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::DecoderPassThrough::onMessageReceived(const sp<AMessage> &msg) {
414*ec779b8eSAndroid Build Coastguard Worker ALOGV("[%s] onMessage: %s", mComponentName.c_str(),
415*ec779b8eSAndroid Build Coastguard Worker msg->debugString().c_str());
416*ec779b8eSAndroid Build Coastguard Worker
417*ec779b8eSAndroid Build Coastguard Worker switch (msg->what()) {
418*ec779b8eSAndroid Build Coastguard Worker case kWhatBufferConsumed:
419*ec779b8eSAndroid Build Coastguard Worker {
420*ec779b8eSAndroid Build Coastguard Worker if (!isStaleReply(msg)) {
421*ec779b8eSAndroid Build Coastguard Worker int32_t size;
422*ec779b8eSAndroid Build Coastguard Worker CHECK(msg->findInt32("size", &size));
423*ec779b8eSAndroid Build Coastguard Worker onBufferConsumed(size);
424*ec779b8eSAndroid Build Coastguard Worker }
425*ec779b8eSAndroid Build Coastguard Worker break;
426*ec779b8eSAndroid Build Coastguard Worker }
427*ec779b8eSAndroid Build Coastguard Worker
428*ec779b8eSAndroid Build Coastguard Worker default:
429*ec779b8eSAndroid Build Coastguard Worker DecoderBase::onMessageReceived(msg);
430*ec779b8eSAndroid Build Coastguard Worker break;
431*ec779b8eSAndroid Build Coastguard Worker }
432*ec779b8eSAndroid Build Coastguard Worker }
433*ec779b8eSAndroid Build Coastguard Worker
434*ec779b8eSAndroid Build Coastguard Worker } // namespace android
435