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

Commit 8c3773d8 authored by Marco Nelissen's avatar Marco Nelissen Committed by Android (Google) Code Review
Browse files

Merge "Convert OggExtractor to V3 format"

parents 5beb4810 e92a5c7d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ apex {
        "libmkvextractor",
        "libmp3extractor",
        "libmp4extractor",
        "liboggextractor",
        "libwavextractor",
    ],
    key: "com.android.media.key",
+8 −8
Original line number Diff line number Diff line
@@ -183,32 +183,32 @@ public:
        mBuffer = buf;
    }

    ~MediaBufferHelperV3() {}
    virtual ~MediaBufferHelperV3() {}

    void release() {
    virtual void release() {
        mBuffer->release(mBuffer->handle);
    }

    void* data() {
    virtual void* data() {
        return mBuffer->data(mBuffer->handle);
    }

    size_t size() {
    virtual size_t size() {
        return mBuffer->size(mBuffer->handle);
    }

    size_t range_offset() {
    virtual size_t range_offset() {
        return mBuffer->range_offset(mBuffer->handle);
    }

    size_t range_length() {
    virtual size_t range_length() {
        return mBuffer->range_length(mBuffer->handle);
    }

    void set_range(size_t offset, size_t length) {
    virtual void set_range(size_t offset, size_t length) {
        mBuffer->set_range(mBuffer->handle, offset, length);
    }
    AMediaFormat *meta_data() {
    virtual AMediaFormat *meta_data() {
        return mBuffer->meta_data(mBuffer->handle);
    }
};
+0 −1
Original line number Diff line number Diff line
@@ -13,7 +13,6 @@ cc_library_shared {

    shared_libs: [
        "liblog",
        "libmediaextractor",
        "libmediandk",
    ],

+123 −50
Original line number Diff line number Diff line
@@ -28,11 +28,8 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/base64.h>
#include <media/stagefright/foundation/ByteUtils.h>
#include <media/stagefright/MediaBufferBase.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaDataBase.h>
#include <media/stagefright/MetaDataUtils.h>
#include <system/audio.h>
#include <utils/String8.h>
@@ -48,7 +45,7 @@ extern "C" {

namespace android {

struct OggSource : public MediaTrackHelperV2 {
struct OggSource : public MediaTrackHelperV3 {
    explicit OggSource(OggExtractor *extractor);

    virtual media_status_t getFormat(AMediaFormat *);
@@ -57,7 +54,7 @@ struct OggSource : public MediaTrackHelperV2 {
    virtual media_status_t stop();

    virtual media_status_t read(
            MediaBufferBase **buffer, const ReadOptions *options = NULL);
            MediaBufferHelperV3 **buffer, const ReadOptions *options = NULL);

protected:
    virtual ~OggSource();
@@ -85,7 +82,7 @@ struct MyOggExtractor {

    status_t seekToTime(int64_t timeUs);
    status_t seekToOffset(off64_t offset);
    virtual media_status_t readNextPacket(MediaBufferBase **buffer) = 0;
    virtual media_status_t readNextPacket(MediaBufferHelperV3 **buffer) = 0;

    status_t init();

@@ -93,6 +90,9 @@ struct MyOggExtractor {
        return AMediaFormat_copy(meta, mFileMeta);
    }

    void setBufferGroup(MediaBufferGroupHelperV3 *group) {
        mBufferGroup = group;
    }
protected:
    struct Page {
        uint64_t mGranulePosition;
@@ -110,6 +110,7 @@ protected:
        int64_t mTimeUs;
    };

    MediaBufferGroupHelperV3 *mBufferGroup;
    DataSourceHelper *mSource;
    off64_t mOffset;
    Page mCurrentPage;
@@ -148,7 +149,7 @@ protected:
    // 1 - bitstream identification header
    // 3 - comment header
    // 5 - codec setup header (Vorbis only)
    virtual media_status_t verifyHeader(MediaBufferBase *buffer, uint8_t type) = 0;
    virtual media_status_t verifyHeader(MediaBufferHelperV3 *buffer, uint8_t type) = 0;

    // Read the next ogg packet from the underlying data source; optionally
    // calculate the timestamp for the output packet whilst pretending
@@ -156,9 +157,9 @@ protected:
    //
    // *buffer is NULL'ed out immediately upon entry, and if successful a new buffer is allocated;
    // clients are responsible for releasing the original buffer.
    media_status_t _readNextPacket(MediaBufferBase **buffer, bool calcVorbisTimestamp);
    media_status_t _readNextPacket(MediaBufferHelperV3 **buffer, bool calcVorbisTimestamp);

    int32_t getPacketBlockSize(MediaBufferBase *buffer);
    int32_t getPacketBlockSize(MediaBufferHelperV3 *buffer);

    void parseFileMetaData();

@@ -182,7 +183,7 @@ struct MyVorbisExtractor : public MyOggExtractor {

    virtual uint64_t approxBitrate() const;

    virtual media_status_t readNextPacket(MediaBufferBase **buffer) {
    virtual media_status_t readNextPacket(MediaBufferHelperV3 **buffer) {
        return _readNextPacket(buffer, /* calcVorbisTimestamp = */ true);
    }

@@ -194,7 +195,7 @@ protected:
        return granulePos * 1000000ll / mVi.rate;
    }

    virtual media_status_t verifyHeader(MediaBufferBase *buffer, uint8_t type);
    virtual media_status_t verifyHeader(MediaBufferHelperV3 *buffer, uint8_t type);
};

struct MyOpusExtractor : public MyOggExtractor {
@@ -212,16 +213,16 @@ struct MyOpusExtractor : public MyOggExtractor {
        return 0;
    }

    virtual media_status_t readNextPacket(MediaBufferBase **buffer);
    virtual media_status_t readNextPacket(MediaBufferHelperV3 **buffer);

protected:
    virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const;
    virtual media_status_t verifyHeader(MediaBufferBase *buffer, uint8_t type);
    virtual media_status_t verifyHeader(MediaBufferHelperV3 *buffer, uint8_t type);

private:
    media_status_t verifyOpusHeader(MediaBufferBase *buffer);
    media_status_t verifyOpusComments(MediaBufferBase *buffer);
    uint32_t getNumSamplesInPacket(MediaBufferBase *buffer) const;
    media_status_t verifyOpusHeader(MediaBufferHelperV3 *buffer);
    media_status_t verifyOpusComments(MediaBufferHelperV3 *buffer);
    uint32_t getNumSamplesInPacket(MediaBufferHelperV3 *buffer) const;

    uint8_t mChannelCount;
    uint16_t mCodecDelay;
@@ -249,7 +250,9 @@ media_status_t OggSource::start() {
    if (mStarted) {
        return AMEDIA_ERROR_INVALID_OPERATION;
    }

    // initialize buffer group with a single small buffer, but a generous upper limit
    mBufferGroup->init(1 /* number of buffers */, 128 /* size */, 64 /* max number of buffers */);
    mExtractor->mImpl->setBufferGroup(mBufferGroup);
    mStarted = true;

    return AMEDIA_OK;
@@ -262,7 +265,7 @@ media_status_t OggSource::stop() {
}

media_status_t OggSource::read(
        MediaBufferBase **out, const ReadOptions *options) {
        MediaBufferHelperV3 **out, const ReadOptions *options) {
    *out = NULL;

    int64_t seekTimeUs;
@@ -274,26 +277,27 @@ media_status_t OggSource::read(
        }
    }

    MediaBufferBase *packet;
    MediaBufferHelperV3 *packet;
    media_status_t err = mExtractor->mImpl->readNextPacket(&packet);

    if (err != AMEDIA_OK) {
        return err;
    }

    AMediaFormat *meta = packet->meta_data();
#if 0
    int64_t timeUs;
    if (packet->meta_data().findInt64(kKeyTime, &timeUs)) {
    if (AMediaFormat_findInt64(meta, AMEDIAFORMAT_KEY_TIME_US, timeStampUs)) {
        ALOGI("found time = %lld us", timeUs);
    } else {
        ALOGI("NO time");
    }
#endif

    packet->meta_data().setInt32(kKeyIsSyncFrame, 1);
    AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);

    *out = packet;

    ALOGV("returning buffer %p", packet);
    return AMEDIA_OK;
}

@@ -304,7 +308,8 @@ MyOggExtractor::MyOggExtractor(
        const char *mimeType,
        size_t numHeaders,
        int64_t seekPreRollUs)
    : mSource(source),
    : mBufferGroup(NULL),
      mSource(source),
      mOffset(0),
      mCurGranulePosition(0),
      mPrevGranulePosition(0),
@@ -573,13 +578,13 @@ ssize_t MyOggExtractor::readPage(off64_t offset, Page *page) {
    return sizeof(header) + page->mNumSegments + totalSize;
}

media_status_t MyOpusExtractor::readNextPacket(MediaBufferBase **out) {
media_status_t MyOpusExtractor::readNextPacket(MediaBufferHelperV3 **out) {
    if (mOffset <= mFirstDataOffset && mStartGranulePosition < 0) {
        // The first sample might not start at time 0; find out where by subtracting
        // the number of samples on the first page from the granule position
        // (position of last complete sample) of the first page. This happens
        // the first time before we attempt to read a packet from the first page.
        MediaBufferBase *mBuf;
        MediaBufferHelperV3 *mBuf;
        uint32_t numSamples = 0;
        uint64_t curGranulePosition = 0;
        while (true) {
@@ -617,24 +622,25 @@ media_status_t MyOpusExtractor::readNextPacket(MediaBufferBase **out) {
    int32_t currentPageSamples;
    // Calculate timestamps by accumulating durations starting from the first sample of a page;
    // We assume that we only seek to page boundaries.
    if ((*out)->meta_data().findInt32(kKeyValidSamples, &currentPageSamples)) {
    AMediaFormat *meta = (*out)->meta_data();
    if (AMediaFormat_getInt32(meta, AMEDIAFORMAT_KEY_VALID_SAMPLES, &currentPageSamples)) {
        // first packet in page
        if (mOffset == mFirstDataOffset) {
            currentPageSamples -= mStartGranulePosition;
            (*out)->meta_data().setInt32(kKeyValidSamples, currentPageSamples);
            AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_VALID_SAMPLES, currentPageSamples);
        }
        mCurGranulePosition = mCurrentPage.mGranulePosition - currentPageSamples;
    }

    int64_t timeUs = getTimeUsOfGranule(mCurGranulePosition);
    (*out)->meta_data().setInt64(kKeyTime, timeUs);
    AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_TIME_US, timeUs);

    uint32_t frames = getNumSamplesInPacket(*out);
    mCurGranulePosition += frames;
    return AMEDIA_OK;
}

uint32_t MyOpusExtractor::getNumSamplesInPacket(MediaBufferBase *buffer) const {
uint32_t MyOpusExtractor::getNumSamplesInPacket(MediaBufferHelperV3 *buffer) const {
    if (buffer == NULL || buffer->range_length() < 1) {
        return 0;
    }
@@ -680,10 +686,66 @@ uint32_t MyOpusExtractor::getNumSamplesInPacket(MediaBufferBase *buffer) const {
    return numSamples;
}

media_status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisTimestamp) {
/*
 * basic mediabuffer implementation used during initial parsing of the
 * header packets, which happens before we have a buffer group
 */
class StandAloneMediaBuffer : public MediaBufferHelperV3 {
private:
    void *mData;
    size_t mSize;
    size_t mOffset;
    size_t mLength;
    AMediaFormat *mFormat;
public:
    StandAloneMediaBuffer(size_t size) : MediaBufferHelperV3(NULL) {
        mSize = size;
        mData = malloc(mSize);
        mOffset = 0;
        mLength = mSize;
        mFormat = AMediaFormat_new();
        ALOGV("created standalone media buffer %p of size %zu", this, mSize);
    }

    ~StandAloneMediaBuffer() override {
        free(mData);
        AMediaFormat_delete(mFormat);
        ALOGV("deleted standalone media buffer %p of size %zu", this, mSize);
    }

    void release() override {
        delete this;
    }

    void* data() override {
        return mData;
    }

    size_t size() override {
        return mSize;
    }

    size_t range_offset() override {
        return mOffset;
    }

    size_t range_length() override {
        return mLength;
    }

    void set_range(size_t offset, size_t length) override {
        mOffset = offset;
        mLength = length;
    }
    AMediaFormat *meta_data() override {
        return mFormat;
    }
};

media_status_t MyOggExtractor::_readNextPacket(MediaBufferHelperV3 **out, bool calcVorbisTimestamp) {
    *out = NULL;

    MediaBufferBase *buffer = NULL;
    MediaBufferHelperV3 *buffer = NULL;
    int64_t timeUs = -1;

    for (;;) {
@@ -719,7 +781,13 @@ media_status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcV
                ALOGE("b/36592202");
                return AMEDIA_ERROR_MALFORMED;
            }
            MediaBufferBase *tmp = MediaBufferBase::Create(fullSize);
            MediaBufferHelperV3 *tmp;
            if (mBufferGroup) {
                mBufferGroup->acquire_buffer(&tmp, false, fullSize);
                ALOGV("acquired buffer %p from group", tmp);
            } else {
                tmp = new StandAloneMediaBuffer(fullSize);
            }
            if (tmp == NULL) {
                if (buffer != NULL) {
                    buffer->release();
@@ -727,6 +795,7 @@ media_status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcV
                ALOGE("b/36592202");
                return AMEDIA_ERROR_MALFORMED;
            }
            AMediaFormat_clear(tmp->meta_data());
            if (buffer != NULL) {
                memcpy(tmp->data(), buffer->data(), buffer->range_length());
                tmp->set_range(0, buffer->range_length());
@@ -756,8 +825,9 @@ media_status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcV
                // We've just read the entire packet.

                if (mFirstPacketInPage) {
                    buffer->meta_data().setInt32(
                            kKeyValidSamples, mCurrentPageSamples);
                    AMediaFormat *meta = buffer->meta_data();
                    AMediaFormat_setInt32(
                            meta, AMEDIAFORMAT_KEY_VALID_SAMPLES, mCurrentPageSamples);
                    mFirstPacketInPage = false;
                }

@@ -778,7 +848,8 @@ media_status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcV
                        mCurrentPage.mPrevPacketPos += actualBlockSize / 2;
                        mCurrentPage.mPrevPacketSize = curBlockSize;
                    }
                    buffer->meta_data().setInt64(kKeyTime, timeUs);
                    AMediaFormat *meta = buffer->meta_data();
                    AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_TIME_US, timeUs);
                }
                *out = buffer;

@@ -824,11 +895,13 @@ media_status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcV
                // is already complete.

                if (timeUs >= 0) {
                    buffer->meta_data().setInt64(kKeyTime, timeUs);
                    AMediaFormat *meta = buffer->meta_data();
                    AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_TIME_US, timeUs);
                }

                buffer->meta_data().setInt32(
                        kKeyValidSamples, mCurrentPageSamples);
                AMediaFormat *meta = buffer->meta_data();
                AMediaFormat_setInt32(
                        meta, AMEDIAFORMAT_KEY_VALID_SAMPLES, mCurrentPageSamples);
                mFirstPacketInPage = false;

                *out = buffer;
@@ -843,7 +916,7 @@ status_t MyOggExtractor::init() {
    AMediaFormat_setString(mMeta, AMEDIAFORMAT_KEY_MIME, mMimeType);

    media_status_t err;
    MediaBufferBase *packet;
    MediaBufferHelperV3 *packet;
    for (size_t i = 0; i < mNumHeaders; ++i) {
        // ignore timestamp for configuration packets
        if ((err = _readNextPacket(&packet, /* calcVorbisTimestamp = */ false)) != AMEDIA_OK) {
@@ -920,7 +993,7 @@ void MyOggExtractor::buildTableOfContents() {
    }
}

int32_t MyOggExtractor::getPacketBlockSize(MediaBufferBase *buffer) {
int32_t MyOggExtractor::getPacketBlockSize(MediaBufferHelperV3 *buffer) {
    const uint8_t *data =
        (const uint8_t *)buffer->data() + buffer->range_offset();

@@ -960,7 +1033,7 @@ int64_t MyOpusExtractor::getTimeUsOfGranule(uint64_t granulePos) const {
    return pcmSamplePosition * 1000000ll / kOpusSampleRate;
}

media_status_t MyOpusExtractor::verifyHeader(MediaBufferBase *buffer, uint8_t type) {
media_status_t MyOpusExtractor::verifyHeader(MediaBufferHelperV3 *buffer, uint8_t type) {
    switch (type) {
        // there are actually no header types defined in the Opus spec; we choose 1 and 3 to mean
        // header and comments such that we can share code with MyVorbisExtractor.
@@ -973,7 +1046,7 @@ media_status_t MyOpusExtractor::verifyHeader(MediaBufferBase *buffer, uint8_t ty
    }
}

media_status_t MyOpusExtractor::verifyOpusHeader(MediaBufferBase *buffer) {
media_status_t MyOpusExtractor::verifyOpusHeader(MediaBufferHelperV3 *buffer) {
    const size_t kOpusHeaderSize = 19;
    const uint8_t *data =
        (const uint8_t *)buffer->data() + buffer->range_offset();
@@ -1001,7 +1074,7 @@ media_status_t MyOpusExtractor::verifyOpusHeader(MediaBufferBase *buffer) {
    return AMEDIA_OK;
}

media_status_t MyOpusExtractor::verifyOpusComments(MediaBufferBase *buffer) {
media_status_t MyOpusExtractor::verifyOpusComments(MediaBufferHelperV3 *buffer) {
    // add artificial framing bit so we can reuse _vorbis_unpack_comment
    int32_t commentSize = buffer->range_length() + 1;
    auto tmp = heapbuffer<uint8_t>(commentSize);
@@ -1094,7 +1167,7 @@ media_status_t MyOpusExtractor::verifyOpusComments(MediaBufferBase *buffer) {
}

media_status_t MyVorbisExtractor::verifyHeader(
        MediaBufferBase *buffer, uint8_t type) {
        MediaBufferHelperV3 *buffer, uint8_t type) {
    const uint8_t *data =
        (const uint8_t *)buffer->data() + buffer->range_offset();

@@ -1262,7 +1335,7 @@ size_t OggExtractor::countTracks() {
    return mInitCheck != OK ? 0 : 1;
}

MediaTrackHelperV2 *OggExtractor::getTrack(size_t index) {
MediaTrackHelperV3 *OggExtractor::getTrack(size_t index) {
    if (index >= 1) {
        return NULL;
    }
@@ -1284,13 +1357,13 @@ media_status_t OggExtractor::getMetaData(AMediaFormat *meta) {
    return mImpl->getFileMetaData(meta);
}

static CMediaExtractorV2* CreateExtractor(
static CMediaExtractorV3* CreateExtractor(
        CDataSource *source,
        void *) {
    return wrapV2(new OggExtractor(new DataSourceHelper(source)));
    return wrapV3(new OggExtractor(new DataSourceHelper(source)));
}

static CreatorFuncV2 Sniff(
static CreatorFuncV3 Sniff(
        CDataSource *source,
        float *confidence,
        void **,
@@ -1311,11 +1384,11 @@ extern "C" {
__attribute__ ((visibility ("default")))
ExtractorDef GETEXTRACTORDEF() {
    return {
        EXTRACTORDEF_VERSION_CURRENT,
        EXTRACTORDEF_VERSION_CURRENT + 1,
        UUID("8cc5cd06-f772-495e-8a62-cba9649374e9"),
        1, // version
        "Ogg Extractor",
        { .v2 = Sniff }
        { .v3 = Sniff }
    };
}

+2 −2
Original line number Diff line number Diff line
@@ -31,11 +31,11 @@ class String8;
struct MyOggExtractor;
struct OggSource;

struct OggExtractor : public MediaExtractorPluginHelperV2 {
struct OggExtractor : public MediaExtractorPluginHelperV3 {
    explicit OggExtractor(DataSourceHelper *source);

    virtual size_t countTracks();
    virtual MediaTrackHelperV2 *getTrack(size_t index);
    virtual MediaTrackHelperV3 *getTrack(size_t index);
    virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);

    virtual media_status_t getMetaData(AMediaFormat *meta);
Loading