summaryrefslogtreecommitdiffstats
path: root/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp')
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp248
1 files changed, 248 insertions, 0 deletions
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
new file mode 100644
index 0000000..ab7906a
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "NuPlayerDecoderPassThrough"
+#include <utils/Log.h>
+#include <inttypes.h>
+
+#include "NuPlayerDecoderPassThrough.h"
+
+#include <media/ICrypto.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+static const int kMaxPendingBuffers = 10;
+static const int kMaxCachedBytes = 200000;
+
+NuPlayer::DecoderPassThrough::DecoderPassThrough(
+ const sp<AMessage> &notify)
+ : Decoder(notify),
+ mNotify(notify),
+ mBufferGeneration(0),
+ mReachedEOS(true),
+ mPendingBuffers(0),
+ mCachedBytes(0),
+ mComponentName("pass through decoder") {
+ mDecoderLooper = new ALooper;
+ mDecoderLooper->setName("NuPlayerDecoderPassThrough");
+ mDecoderLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
+}
+
+NuPlayer::DecoderPassThrough::~DecoderPassThrough() {
+}
+
+void NuPlayer::DecoderPassThrough::configure(const sp<AMessage> &format) {
+ sp<AMessage> msg = new AMessage(kWhatConfigure, id());
+ msg->setMessage("format", format);
+ msg->post();
+}
+
+void NuPlayer::DecoderPassThrough::init() {
+ mDecoderLooper->registerHandler(this);
+}
+
+void NuPlayer::DecoderPassThrough::signalFlush() {
+ (new AMessage(kWhatFlush, id()))->post();
+}
+
+void NuPlayer::DecoderPassThrough::signalResume() {
+ (new AMessage(kWhatResume, id()))->post();
+}
+
+void NuPlayer::DecoderPassThrough::initiateShutdown() {
+ (new AMessage(kWhatShutdown, id()))->post();
+}
+
+bool NuPlayer::DecoderPassThrough::supportsSeamlessFormatChange(
+ const sp<AMessage> & /* targetFormat */) const {
+ return true;
+}
+
+void NuPlayer::DecoderPassThrough::onConfigure(const sp<AMessage> &format) {
+ ALOGV("[%s] onConfigure", mComponentName.c_str());
+ mPendingBuffers = 0;
+ mCachedBytes = 0;
+ mReachedEOS = false;
+ ++mBufferGeneration;
+
+ requestABuffer();
+
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kWhatOutputFormatChanged);
+ notify->setMessage("format", format);
+ notify->post();
+}
+
+bool NuPlayer::DecoderPassThrough::isStaleReply(const sp<AMessage> &msg) {
+ int32_t generation;
+ CHECK(msg->findInt32("generation", &generation));
+ return generation != mBufferGeneration;
+}
+
+void NuPlayer::DecoderPassThrough::requestABuffer() {
+ if (mCachedBytes >= kMaxCachedBytes || mReachedEOS) {
+ ALOGV("[%s] mReachedEOS=%d, max pending buffers(%d:%d)",
+ mComponentName.c_str(), (mReachedEOS ? 1 : 0),
+ mPendingBuffers, kMaxPendingBuffers);
+ return;
+ }
+
+ sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, id());
+ reply->setInt32("generation", mBufferGeneration);
+
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kWhatFillThisBuffer);
+ notify->setMessage("reply", reply);
+ notify->post();
+ mPendingBuffers++;
+
+ // pending buffers will already result in requestABuffer
+ if (mPendingBuffers < kMaxPendingBuffers) {
+ sp<AMessage> message = new AMessage(kWhatRequestABuffer, id());
+ message->setInt32("generation", mBufferGeneration);
+ message->post();
+ }
+ return;
+}
+
+void android::NuPlayer::DecoderPassThrough::onInputBufferFilled(
+ const sp<AMessage> &msg) {
+ if (mReachedEOS) {
+ return;
+ }
+
+ sp<ABuffer> buffer;
+ msg->findBuffer("buffer", &buffer);
+ if (buffer == NULL) {
+ mReachedEOS = true;
+
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kWhatEOS);
+ notify->setInt32("err", ERROR_END_OF_STREAM);
+ notify->post();
+ return;
+ }
+
+ mCachedBytes += buffer->size();
+
+ sp<AMessage> reply = new AMessage(kWhatBufferConsumed, id());
+ reply->setInt32("generation", mBufferGeneration);
+ reply->setInt32("size", buffer->size());
+
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kWhatDrainThisBuffer);
+ notify->setBuffer("buffer", buffer);
+ notify->setMessage("reply", reply);
+ notify->post();
+}
+
+void NuPlayer::DecoderPassThrough::onBufferConsumed(int32_t size) {
+ mPendingBuffers--;
+ mCachedBytes -= size;
+ requestABuffer();
+}
+
+void NuPlayer::DecoderPassThrough::onFlush() {
+ ++mBufferGeneration;
+
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kWhatFlushCompleted);
+ notify->post();
+ mPendingBuffers = 0;
+ mCachedBytes = 0;
+ mReachedEOS = false;
+}
+
+void NuPlayer::DecoderPassThrough::onShutdown() {
+ ++mBufferGeneration;
+
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kWhatShutdownCompleted);
+ notify->post();
+ mReachedEOS = true;
+}
+
+void NuPlayer::DecoderPassThrough::onMessageReceived(const sp<AMessage> &msg) {
+ ALOGV("[%s] onMessage: %s", mComponentName.c_str(),
+ msg->debugString().c_str());
+
+ switch (msg->what()) {
+ case kWhatConfigure:
+ {
+ sp<AMessage> format;
+ CHECK(msg->findMessage("format", &format));
+ onConfigure(format);
+ break;
+ }
+
+ case kWhatRequestABuffer:
+ {
+ if (!isStaleReply(msg)) {
+ requestABuffer();
+ }
+
+ break;
+ }
+
+ case kWhatInputBufferFilled:
+ {
+ if (!isStaleReply(msg)) {
+ onInputBufferFilled(msg);
+ }
+ break;
+ }
+
+ case kWhatBufferConsumed:
+ {
+ if (!isStaleReply(msg)) {
+ int32_t size;
+ CHECK(msg->findInt32("size", &size));
+ onBufferConsumed(size);
+ }
+ break;
+ }
+
+ case kWhatFlush:
+ {
+ onFlush();
+ break;
+ }
+
+ case kWhatResume:
+ {
+ requestABuffer();
+ break;
+ }
+
+ case kWhatShutdown:
+ {
+ onShutdown();
+ break;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+}
+
+} // namespace android