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

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

Merge "Proper recovery of timestamp information in the transport stream parser."

parents 10f0d3f2 a093f920
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -21,8 +21,8 @@

#include "pvmp4audiodecoder_api.h"

#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaData.h>

@@ -84,7 +84,7 @@ status_t AACDecoder::initCheck() {
    sp<MetaData> meta = mSource->getFormat();
    if (meta->findData(kKeyESDS, &type, &data, &size)) {
        ESDS esds((const char *)data, size);
        CHECK_EQ(esds.InitCheck(), OK);
        CHECK_EQ(esds.InitCheck(), (status_t)OK);

        const void *codec_specific_data;
        size_t codec_specific_data_size;
@@ -197,7 +197,7 @@ status_t AACDecoder::read(
    }

    MediaBuffer *buffer;
    CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);
    CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), (status_t)OK);

    mConfig->pInputBuffer =
        (UChar *)mInputBuffer->data() + mInputBuffer->range_offset();
+67 −11
Original line number Diff line number Diff line
@@ -45,7 +45,7 @@ void ElementaryStreamQueue::clear() {
        mBuffer->setRange(0, 0);
    }

    mTimestamps.clear();
    mRangeInfos.clear();
    mFormat.clear();
}

@@ -171,7 +171,17 @@ status_t ElementaryStreamQueue::appendData(
    memcpy(mBuffer->data() + mBuffer->size(), data, size);
    mBuffer->setRange(0, mBuffer->size() + size);

    mTimestamps.push_back(timeUs);
    RangeInfo info;
    info.mLength = size;
    info.mTimestampUs = timeUs;
    mRangeInfos.push_back(info);

#if 0
    if (mMode == AAC) {
        LOGI("size = %d, timeUs = %.2f secs", size, timeUs / 1E6);
        hexdump(data, size);
    }
#endif

    return OK;
}
@@ -186,6 +196,7 @@ sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnit() {
}

sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitAAC() {
    Vector<size_t> ranges;
    Vector<size_t> frameOffsets;
    Vector<size_t> frameSizes;
    size_t auSize = 0;
@@ -239,6 +250,7 @@ sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitAAC() {

        size_t headerSize = protection_absent ? 7 : 9;

        ranges.push(aac_frame_length);
        frameOffsets.push(offset + headerSize);
        frameSizes.push(aac_frame_length - headerSize);
        auSize += aac_frame_length - headerSize;
@@ -250,11 +262,23 @@ sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitAAC() {
        return NULL;
    }

    int64_t timeUs = -1;

    for (size_t i = 0; i < ranges.size(); ++i) {
        int64_t tmpUs = fetchTimestamp(ranges.itemAt(i));

        if (i == 0) {
            timeUs = tmpUs;
        }
    }

    sp<ABuffer> accessUnit = new ABuffer(auSize);
    size_t dstOffset = 0;
    for (size_t i = 0; i < frameOffsets.size(); ++i) {
        size_t frameOffset = frameOffsets.itemAt(i);

        memcpy(accessUnit->data() + dstOffset,
               mBuffer->data() + frameOffsets.itemAt(i),
               mBuffer->data() + frameOffset,
               frameSizes.itemAt(i));

        dstOffset += frameSizes.itemAt(i);
@@ -264,15 +288,48 @@ sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitAAC() {
            mBuffer->size() - offset);
    mBuffer->setRange(0, mBuffer->size() - offset);

    CHECK_GT(mTimestamps.size(), 0u);
    int64_t timeUs = *mTimestamps.begin();
    mTimestamps.erase(mTimestamps.begin());

    if (timeUs >= 0) {
        accessUnit->meta()->setInt64("time", timeUs);
    } else {
        LOGW("no time for AAC access unit");
    }

    return accessUnit;
}

int64_t ElementaryStreamQueue::fetchTimestamp(size_t size) {
    int64_t timeUs = -1;
    bool first = true;

    while (size > 0) {
        CHECK(!mRangeInfos.empty());

        RangeInfo *info = &*mRangeInfos.begin();

        if (first) {
            timeUs = info->mTimestampUs;
            first = false;
        }

        if (info->mLength > size) {
            info->mLength -= size;

            if (first) {
                info->mTimestampUs = -1;
            }

            size = 0;
        } else {
            size -= info->mLength;

            mRangeInfos.erase(mRangeInfos.begin());
            info = NULL;
        }
    }

    return timeUs;
}

// static
sp<MetaData> ElementaryStreamQueue::MakeAACCodecSpecificData(
        unsigned profile, unsigned sampling_freq_index,
@@ -410,9 +467,8 @@ sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitH264() {

            mBuffer->setRange(0, mBuffer->size() - nextScan);

            CHECK_GT(mTimestamps.size(), 0u);
            int64_t timeUs = *mTimestamps.begin();
            mTimestamps.erase(mTimestamps.begin());
            int64_t timeUs = fetchTimestamp(nextScan);
            CHECK_GE(timeUs, 0ll);

            accessUnit->meta()->setInt64("time", timeUs);

+10 −1
Original line number Diff line number Diff line
@@ -42,16 +42,25 @@ struct ElementaryStreamQueue {
    sp<MetaData> getFormat();

private:
    struct RangeInfo {
        int64_t mTimestampUs;
        size_t mLength;
    };

    Mode mMode;

    sp<ABuffer> mBuffer;
    List<int64_t> mTimestamps;
    List<RangeInfo> mRangeInfos;

    sp<MetaData> mFormat;

    sp<ABuffer> dequeueAccessUnitH264();
    sp<ABuffer> dequeueAccessUnitAAC();

    // consume a logical (compressed) access unit of size "size",
    // returns its timestamp in us (or -1 if no time information).
    int64_t fetchTimestamp(size_t size);

    static sp<MetaData> MakeAACCodecSpecificData(
            unsigned profile, unsigned sampling_freq_index,
            unsigned channel_configuration);