NuPlayerDecoderPassThrough.cpp revision c5cc2e21602182c7ab4df1d7eba40f18037c1818
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
31namespace android {
32
33static 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.
36static const size_t kMaxPendingBuffers = 1 + (kMaxCachedBytes / NuPlayer::kAggregateBufferSizeBytes);
37
38NuPlayer::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
53NuPlayer::DecoderPassThrough::~DecoderPassThrough() {
54}
55
56void 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
62void NuPlayer::DecoderPassThrough::init() {
63    mDecoderLooper->registerHandler(this);
64}
65
66void NuPlayer::DecoderPassThrough::signalFlush() {
67    (new AMessage(kWhatFlush, id()))->post();
68}
69
70void NuPlayer::DecoderPassThrough::signalResume() {
71    (new AMessage(kWhatResume, id()))->post();
72}
73
74void NuPlayer::DecoderPassThrough::initiateShutdown() {
75    (new AMessage(kWhatShutdown, id()))->post();
76}
77
78bool NuPlayer::DecoderPassThrough::supportsSeamlessFormatChange(
79        const sp<AMessage> & /* targetFormat */) const {
80    return true;
81}
82
83void 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
99bool NuPlayer::DecoderPassThrough::isStaleReply(const sp<AMessage> &msg) {
100    int32_t generation;
101    CHECK(msg->findInt32("generation", &generation));
102    return generation != mBufferGeneration;
103}
104
105bool 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
130void 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
165void 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
173void 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
185void NuPlayer::DecoderPassThrough::requestMaxBuffers() {
186    for (size_t i = 0; i < kMaxPendingBuffers; i++) {
187        if (!requestABuffer()) {
188            break;
189        }
190    }
191}
192
193void 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
202void 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