Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1abf1c59 authored by Andreas Huber's avatar Andreas Huber Committed by Android (Google) Code Review
Browse files

Merge "The decoder wrapper is no longer needed. Also disable building old-style decoders."

parents 415c842a 93c612e2
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -97,7 +97,7 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/RSTest_intermedi
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/hardware/IUsbManager.java)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/nfc)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)

$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libstagefright_intermediates)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
+0 −1
Original line number Diff line number Diff line
@@ -8,7 +8,6 @@ LOCAL_SRC_FILES:= \
        NuPlayerDriver.cpp              \
        NuPlayerRenderer.cpp            \
        NuPlayerStreamListener.cpp      \
        DecoderWrapper.cpp              \
        StreamingSource.cpp             \

LOCAL_C_INCLUDES := \
+0 −576
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 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 "DecoderWrapper"
#include <utils/Log.h>

#include "DecoderWrapper.h"

#include "AACDecoder.h"

#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/ACodec.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>

namespace android {

struct DecoderWrapper::WrapperSource : public MediaSource {
    WrapperSource(
            const sp<MetaData> &meta,
            const sp<AMessage> &notify);

    virtual status_t start(MetaData *params);
    virtual status_t stop();
    virtual sp<MetaData> getFormat();

    virtual status_t read(
            MediaBuffer **buffer, const ReadOptions *options);

    void queueBuffer(const sp<ABuffer> &buffer);
    void queueEOS(status_t finalResult);
    void clear();

protected:
    virtual ~WrapperSource();

private:
    Mutex mLock;
    Condition mCondition;

    sp<MetaData> mMeta;
    sp<AMessage> mNotify;

    List<sp<ABuffer> > mQueue;
    status_t mFinalResult;

    DISALLOW_EVIL_CONSTRUCTORS(WrapperSource);
};

DecoderWrapper::WrapperSource::WrapperSource(
        const sp<MetaData> &meta, const sp<AMessage> &notify)
    : mMeta(meta),
      mNotify(notify),
      mFinalResult(OK) {
}

DecoderWrapper::WrapperSource::~WrapperSource() {
}

status_t DecoderWrapper::WrapperSource::start(MetaData *params) {
    return OK;
}

status_t DecoderWrapper::WrapperSource::stop() {
    return OK;
}

sp<MetaData> DecoderWrapper::WrapperSource::getFormat() {
    return mMeta;
}

status_t DecoderWrapper::WrapperSource::read(
        MediaBuffer **out, const ReadOptions *options) {
    Mutex::Autolock autoLock(mLock);

    bool requestedBuffer = false;

    while (mQueue.empty() && mFinalResult == OK) {
        if (!requestedBuffer) {
            mNotify->dup()->post();
            requestedBuffer = true;
        }

        mCondition.wait(mLock);
    }

    if (mQueue.empty()) {
        return mFinalResult;
    }

    sp<ABuffer> src = *mQueue.begin();
    mQueue.erase(mQueue.begin());

    MediaBuffer *dst = new MediaBuffer(src->size());
    memcpy(dst->data(), src->data(), src->size());

    int64_t timeUs;
    CHECK(src->meta()->findInt64("timeUs", &timeUs));

    dst->meta_data()->setInt64(kKeyTime, timeUs);

    *out = dst;

    return OK;
}

void DecoderWrapper::WrapperSource::queueBuffer(const sp<ABuffer> &buffer) {
    Mutex::Autolock autoLock(mLock);
    mQueue.push_back(buffer);
    mCondition.broadcast();
}

void DecoderWrapper::WrapperSource::queueEOS(status_t finalResult) {
    CHECK_NE(finalResult, (status_t)OK);

    Mutex::Autolock autoLock(mLock);
    mFinalResult = finalResult;
    mCondition.broadcast();
}

void DecoderWrapper::WrapperSource::clear() {
    Mutex::Autolock autoLock(mLock);
    mQueue.clear();
    mFinalResult = OK;
}

////////////////////////////////////////////////////////////////////////////////

struct DecoderWrapper::WrapperReader : public AHandler {
    WrapperReader(
            const sp<MediaSource> &decoder,
            const sp<AMessage> &notify);

    void start();
    void stop();
    void readMore(bool flush = false);

protected:
    virtual ~WrapperReader();

    virtual void onMessageReceived(const sp<AMessage> &msg);

private:
    enum {
        kWhatRead
    };

    sp<MediaSource> mDecoder;
    sp<AMessage> mNotify;
    bool mEOS;
    bool mSentFormat;

    void sendFormatChange();

    DISALLOW_EVIL_CONSTRUCTORS(WrapperReader);
};

DecoderWrapper::WrapperReader::WrapperReader(
        const sp<MediaSource> &decoder, const sp<AMessage> &notify)
    : mDecoder(decoder),
      mNotify(notify),
      mEOS(false),
      mSentFormat(false) {
}

DecoderWrapper::WrapperReader::~WrapperReader() {
}

void DecoderWrapper::WrapperReader::start() {
    CHECK_EQ(mDecoder->start(), (status_t)OK);
    readMore();
}

void DecoderWrapper::WrapperReader::stop() {
    CHECK_EQ(mDecoder->stop(), (status_t)OK);
}

void DecoderWrapper::WrapperReader::readMore(bool flush) {
    if (!flush && mEOS) {
        return;
    }

    sp<AMessage> msg = new AMessage(kWhatRead, id());
    msg->setInt32("flush", static_cast<int32_t>(flush));
    msg->post();
}

void DecoderWrapper::WrapperReader::onMessageReceived(
        const sp<AMessage> &msg) {
    switch (msg->what()) {
        case kWhatRead:
        {
            int32_t flush;
            CHECK(msg->findInt32("flush", &flush));

            MediaSource::ReadOptions options;
            if (flush) {
                // Dummy seek
                options.setSeekTo(0);
                mEOS = false;
            }

            CHECK(!mEOS);

            MediaBuffer *src;
            status_t err = mDecoder->read(&src, &options);

            if (err == OK) {
                if (!mSentFormat) {
                    sendFormatChange();
                    mSentFormat = true;
                }

                sp<AMessage> notify = mNotify->dup();

                sp<AMessage> realNotify;
                CHECK(notify->findMessage("real-notify", &realNotify));

                realNotify->setInt32("what", ACodec::kWhatDrainThisBuffer);

                sp<ABuffer> dst = new ABuffer(src->range_length());
                memcpy(dst->data(),
                       (const uint8_t *)src->data() + src->range_offset(),
                       src->range_length());

                int64_t timeUs;
                CHECK(src->meta_data()->findInt64(kKeyTime, &timeUs));
                src->release();
                src = NULL;

                dst->meta()->setInt64("timeUs", timeUs);

                realNotify->setObject("buffer", dst);

                notify->post();
            } else if (err == INFO_FORMAT_CHANGED) {
                sendFormatChange();

                readMore(false /* flush */);
            } else {
                sp<AMessage> notify = mNotify->dup();

                sp<AMessage> realNotify;
                CHECK(notify->findMessage("real-notify", &realNotify));

                realNotify->setInt32("what", ACodec::kWhatEOS);
                mEOS = true;

                notify->post();
            }
            break;
        }

        default:
            TRESPASS();
            break;
    }
}

void DecoderWrapper::WrapperReader::sendFormatChange() {
    sp<AMessage> notify = mNotify->dup();

    sp<AMessage> realNotify;
    CHECK(notify->findMessage("real-notify", &realNotify));

    realNotify->setInt32("what", ACodec::kWhatOutputFormatChanged);

    sp<MetaData> meta = mDecoder->getFormat();

    const char *mime;
    CHECK(meta->findCString(kKeyMIMEType, &mime));

    realNotify->setString("mime", mime);

    if (!strncasecmp("audio/", mime, 6)) {
        int32_t numChannels;
        CHECK(meta->findInt32(kKeyChannelCount, &numChannels));

        int32_t sampleRate;
        CHECK(meta->findInt32(kKeySampleRate, &sampleRate));

        realNotify->setInt32("channel-count", numChannels);
        realNotify->setInt32("sample-rate", sampleRate);
    } else {
        CHECK(!strncasecmp("video/", mime, 6));

        int32_t width, height;
        CHECK(meta->findInt32(kKeyWidth, &width));
        CHECK(meta->findInt32(kKeyHeight, &height));

        realNotify->setInt32("width", width);
        realNotify->setInt32("height", height);

        int32_t cropLeft, cropTop, cropRight, cropBottom;
        if (!meta->findRect(
                    kKeyCropRect,
                    &cropLeft, &cropTop, &cropRight, &cropBottom)) {
            cropLeft = 0;
            cropTop = 0;
            cropRight = width - 1;
            cropBottom = height - 1;
        }

        realNotify->setRect("crop", cropLeft, cropTop, cropRight, cropBottom);
    }

    notify->post();

    mSentFormat = true;
}

////////////////////////////////////////////////////////////////////////////////

DecoderWrapper::DecoderWrapper()
    : mNumOutstandingInputBuffers(0),
      mNumOutstandingOutputBuffers(0),
      mNumPendingDecodes(0),
      mFlushing(false) {
}

DecoderWrapper::~DecoderWrapper() {
}

void DecoderWrapper::setNotificationMessage(const sp<AMessage> &msg) {
    mNotify = msg;
}

void DecoderWrapper::initiateSetup(const sp<AMessage> &msg) {
    msg->setWhat(kWhatSetup);
    msg->setTarget(id());
    msg->post();
}

void DecoderWrapper::initiateShutdown() {
    (new AMessage(kWhatShutdown, id()))->post();
}

void DecoderWrapper::signalFlush() {
    (new AMessage(kWhatFlush, id()))->post();
}

void DecoderWrapper::signalResume() {
    (new AMessage(kWhatResume, id()))->post();
}

void DecoderWrapper::onMessageReceived(const sp<AMessage> &msg) {
    switch (msg->what()) {
        case kWhatSetup:
            onSetup(msg);
            break;

        case kWhatShutdown:
            onShutdown();
            break;

        case kWhatInputDataRequested:
        {
            postFillBuffer();
            ++mNumOutstandingInputBuffers;
            break;
        }

        case kWhatInputBufferFilled:
        {
            CHECK_GT(mNumOutstandingInputBuffers, 0);
            --mNumOutstandingInputBuffers;

            if (mFlushing) {
                mSource->queueEOS(INFO_DISCONTINUITY);

                completeFlushIfPossible();
                break;
            }

            sp<RefBase> obj;
            if (!msg->findObject("buffer", &obj)) {
                int32_t err = OK;
                CHECK(msg->findInt32("err", &err));

                mSource->queueEOS(err);
                break;
            }

            sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get());

            mSource->queueBuffer(buffer);
            break;
        }

        case kWhatFillBufferDone:
        {
            sp<AMessage> notify;
            CHECK(msg->findMessage("real-notify", &notify));

            int32_t what;
            CHECK(notify->findInt32("what", &what));

            if (what == ACodec::kWhatDrainThisBuffer) {
                CHECK_GT(mNumPendingDecodes, 0);
                --mNumPendingDecodes;

                sp<AMessage> reply =
                    new AMessage(kWhatOutputBufferDrained, id());

                notify->setMessage("reply", reply);

                ++mNumOutstandingOutputBuffers;
            } else if (what == ACodec::kWhatEOS) {
                CHECK_GT(mNumPendingDecodes, 0);
                --mNumPendingDecodes;

                if (mFlushing) {
                    completeFlushIfPossible();
                    break;
                }
            }

            notify->post();
            break;
        }

        case kWhatOutputBufferDrained:
        {
            CHECK_GT(mNumOutstandingOutputBuffers, 0);
            --mNumOutstandingOutputBuffers;

            if (mFlushing) {
                completeFlushIfPossible();
                break;
            }

            ++mNumPendingDecodes;
            mReader->readMore();
            break;
        }

        case kWhatFlush:
        {
            onFlush();
            break;
        }

        case kWhatResume:
        {
            onResume();
            break;
        }

        default:
            TRESPASS();
            break;
    }
}

void DecoderWrapper::onSetup(const sp<AMessage> &msg) {
    AString mime;
    CHECK(msg->findString("mime", &mime));

    CHECK(!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC));

    int32_t numChannels, sampleRate;
    CHECK(msg->findInt32("channel-count", &numChannels));
    CHECK(msg->findInt32("sample-rate", &sampleRate));

    sp<RefBase> obj;
    CHECK(msg->findObject("esds", &obj));
    sp<ABuffer> esds = static_cast<ABuffer *>(obj.get());

    sp<MetaData> meta = new MetaData;
    meta->setCString(kKeyMIMEType, mime.c_str());
    meta->setInt32(kKeySampleRate, sampleRate);
    meta->setInt32(kKeyChannelCount, numChannels);
    meta->setData(kKeyESDS, 0, esds->data(), esds->size());

    mSource = new WrapperSource(
            meta, new AMessage(kWhatInputDataRequested, id()));

    sp<MediaSource> decoder = new AACDecoder(mSource);

    mReaderLooper = new ALooper;
    mReaderLooper->setName("DecoderWrapper looper");

    mReaderLooper->start(
            false, /* runOnCallingThread */
            false, /* canCallJava */
            PRIORITY_AUDIO);

    sp<AMessage> notify = new AMessage(kWhatFillBufferDone, id());
    notify->setMessage("real-notify", mNotify);

    mReader = new WrapperReader(decoder, notify);
    mReaderLooper->registerHandler(mReader);

    mReader->start();
    ++mNumPendingDecodes;
}

void DecoderWrapper::onShutdown() {
    mReaderLooper->stop();
    mReaderLooper.clear();

    mReader->stop();
    mReader.clear();

    mSource.clear();

    mNumOutstandingInputBuffers = 0;
    mNumOutstandingOutputBuffers = 0;
    mNumPendingDecodes = 0;
    mFlushing = false;

    sp<AMessage> notify = mNotify->dup();
    notify->setInt32("what", ACodec::kWhatShutdownCompleted);
    notify->post();
}

void DecoderWrapper::postFillBuffer() {
    sp<AMessage> notify = mNotify->dup();
    notify->setInt32("what", ACodec::kWhatFillThisBuffer);
    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, id());
    notify->setMessage("reply", reply);
    notify->post();
}

void DecoderWrapper::onFlush() {
    CHECK(!mFlushing);
    mFlushing = true;

    completeFlushIfPossible();
}

void DecoderWrapper::completeFlushIfPossible() {
    CHECK(mFlushing);

    if (mNumOutstandingInputBuffers > 0
            || mNumOutstandingOutputBuffers > 0
            || mNumPendingDecodes > 0) {
        return;
    }

    mFlushing = false;

    sp<AMessage> notify = mNotify->dup();
    notify->setInt32("what", ACodec::kWhatFlushCompleted);
    notify->post();
}

void DecoderWrapper::onResume() {
    CHECK(!mFlushing);

    ++mNumPendingDecodes;

    mSource->clear();
    mReader->readMore(true /* flush */);
}

}  // namespace android
+0 −82
Original line number Diff line number Diff line
/*
 * Copyright (C) 2010 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.
 */

#ifndef DECODER_WRAPPER_H_

#define DECODER_WRAPPER_H_

#include <media/stagefright/foundation/AHandler.h>

namespace android {

struct MediaSource;

struct DecoderWrapper : public AHandler {
    DecoderWrapper();

    void setNotificationMessage(const sp<AMessage> &msg);
    void initiateSetup(const sp<AMessage> &msg);
    void initiateShutdown();
    void signalFlush();
    void signalResume();

protected:
    virtual ~DecoderWrapper();

    virtual void onMessageReceived(const sp<AMessage> &msg);

private:
    struct WrapperSource;
    struct WrapperReader;

    enum {
        kWhatSetup,
        kWhatInputBufferFilled,
        kWhatOutputBufferDrained,
        kWhatShutdown,
        kWhatFillBufferDone,
        kWhatInputDataRequested,
        kWhatFlush,
        kWhatResume,
    };

    sp<AMessage> mNotify;

    sp<WrapperSource> mSource;

    sp<ALooper> mReaderLooper;
    sp<WrapperReader> mReader;

    int32_t mNumOutstandingInputBuffers;
    int32_t mNumOutstandingOutputBuffers;
    int32_t mNumPendingDecodes;
    bool mFlushing;

    void onSetup(const sp<AMessage> &msg);
    void onShutdown();
    void onFlush();
    void onResume();

    void postFillBuffer();
    void completeFlushIfPossible();

    DISALLOW_EVIL_CONSTRUCTORS(DecoderWrapper);
};

}  // namespace android

#endif  // DECODER_WRAPPER_H_
+4 −30
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@

#include "NuPlayerDecoder.h"

#include "DecoderWrapper.h"
#include "ESDS.h"

#include <media/stagefright/foundation/ABuffer.h>
@@ -47,7 +46,6 @@ NuPlayer::Decoder::~Decoder() {

void NuPlayer::Decoder::configure(const sp<MetaData> &meta) {
    CHECK(mCodec == NULL);
    CHECK(mWrapper == NULL);

    const char *mime;
    CHECK(meta->findCString(kKeyMIMEType, &mime));
@@ -61,20 +59,12 @@ void NuPlayer::Decoder::configure(const sp<MetaData> &meta) {
        format->setObject("native-window", mNativeWindow);
    }

    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
        mWrapper = new DecoderWrapper;
        looper()->registerHandler(mWrapper);

        mWrapper->setNotificationMessage(notifyMsg);
        mWrapper->initiateSetup(format);
    } else {
    mCodec = new ACodec;
    looper()->registerHandler(mCodec);

    mCodec->setNotificationMessage(notifyMsg);
    mCodec->initiateSetup(format);
}
}

void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
    switch (msg->what()) {
@@ -214,7 +204,6 @@ sp<AMessage> NuPlayer::Decoder::makeFormat(const sp<MetaData> &meta) {

        msg->setObject("csd", buffer);
    } else if (meta->findData(kKeyESDS, &type, &data, &size)) {
#if 0
        ESDS esds((const char *)data, size);
        CHECK_EQ(esds.InitCheck(), (status_t)OK);

@@ -230,12 +219,6 @@ sp<AMessage> NuPlayer::Decoder::makeFormat(const sp<MetaData> &meta) {

        buffer->meta()->setInt32("csd", true);
        mCSD.push(buffer);
#else
        sp<ABuffer> buffer = new ABuffer(size);
        memcpy(buffer->data(), data, size);

        msg->setObject("esds", buffer);
#endif
    }

    return msg;
@@ -270,27 +253,18 @@ void NuPlayer::Decoder::onFillThisBuffer(const sp<AMessage> &msg) {
void NuPlayer::Decoder::signalFlush() {
    if (mCodec != NULL) {
        mCodec->signalFlush();
    } else {
        CHECK(mWrapper != NULL);
        mWrapper->signalFlush();
    }
}

void NuPlayer::Decoder::signalResume() {
    if (mCodec != NULL) {
        mCodec->signalResume();
    } else {
        CHECK(mWrapper != NULL);
        mWrapper->signalResume();
    }
}

void NuPlayer::Decoder::initiateShutdown() {
    if (mCodec != NULL) {
        mCodec->initiateShutdown();
    } else {
        CHECK(mWrapper != NULL);
        mWrapper->initiateShutdown();
    }
}

Loading