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

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

Merge "Fix static sample table processing, add support for h.263 video." into jb-mr1-dev

parents 9352d116 b9787142
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -349,7 +349,10 @@ int main(int argc, char **argv) {

    size_t len = strlen(argv[1]);
    if ((!usemp4 && len >= 3 && !strcasecmp(".ts", &argv[1][len - 3])) ||
        (usemp4 && len >= 4 && !strcasecmp(".mp4", &argv[1][len - 4]))) {
        (usemp4 && len >= 4 &&
         (!strcasecmp(".mp4", &argv[1][len - 4])
            || !strcasecmp(".3gp", &argv[1][len- 4])
            || !strcasecmp(".3g2", &argv[1][len- 4])))) {
        int fd = open(argv[1], O_RDONLY);

        if (fd < 0) {
+20 −0
Original line number Diff line number Diff line
@@ -271,6 +271,19 @@ void Parser::onMessageReceived(const sp<AMessage> &msg) {
            mBuffer->setRange(0, mBuffer->size());

            size_t maxBytesToRead = mBuffer->capacity() - mBuffer->size();

            if (maxBytesToRead < needed) {
                ALOGI("resizing buffer.");

                sp<ABuffer> newBuffer =
                    new ABuffer((mBuffer->size() + needed + 1023) & ~1023);
                memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size());
                newBuffer->setRange(0, mBuffer->size());

                mBuffer = newBuffer;
                maxBytesToRead = mBuffer->capacity() - mBuffer->size();
            }

            CHECK_GE(maxBytesToRead, needed);

            ssize_t n = mSource->readAt(
@@ -1023,6 +1036,11 @@ status_t Parser::parseVisualSampleEntry(
        case FOURCC('m', 'p', '4', 'v'):
            format->setString("mime", MEDIA_MIMETYPE_VIDEO_MPEG4);
            break;
        case FOURCC('s', '2', '6', '3'):
        case FOURCC('h', '2', '6', '3'):
        case FOURCC('H', '2', '6', '3'):
            format->setString("mime", MEDIA_MIMETYPE_VIDEO_H263);
            break;
        default:
            format->setString("mime", "application/octet-stream");
            break;
@@ -1062,11 +1080,13 @@ status_t Parser::parseAudioSampleEntry(
        case FOURCC('m', 'p', '4', 'a'):
            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
            break;

        case FOURCC('s', 'a', 'm', 'r'):
            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
            format->setInt32("channel-count", 1);
            format->setInt32("sample-rate", 8000);
            break;

        case FOURCC('s', 'a', 'w', 'b'):
            format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
            format->setInt32("channel-count", 1);
+28 −54
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <media/stagefright/Utils.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/hexdump.h>

namespace android {

@@ -79,6 +80,7 @@ bool Parser::DynamicTrackFragment::complete() const {
Parser::StaticTrackFragment::StaticTrackFragment()
    : mSampleIndex(0),
      mSampleCount(0),
      mChunkIndex(0),
      mSampleToChunkIndex(-1),
      mSampleToChunkRemaining(0),
      mPrevChunkIndex(0xffffffff),
@@ -149,37 +151,31 @@ void Parser::StaticTrackFragment::updateSampleInfo() {
    mSampleInfo.mSampleDescIndex =
        U32_AT(mSampleToChunk->data() + 8 + 12 * mSampleToChunkIndex + 8);

    uint32_t chunkIndex =
        U32_AT(mSampleToChunk->data() + 8 + 12 * mSampleToChunkIndex);

    CHECK_GE(chunkIndex, 1);
    --chunkIndex;

    if (chunkIndex != mPrevChunkIndex) {
        mPrevChunkIndex = chunkIndex;
    if (mChunkIndex != mPrevChunkIndex) {
        mPrevChunkIndex = mChunkIndex;

        if (mChunkOffsets != NULL) {
            uint32_t entryCount = U32_AT(mChunkOffsets->data() + 4);

            if (chunkIndex >= entryCount) {
            if (mChunkIndex >= entryCount) {
                mSampleIndex = mSampleCount;
                return;
            }

            mNextSampleOffset =
                U32_AT(mChunkOffsets->data() + 8 + 4 * chunkIndex);
                U32_AT(mChunkOffsets->data() + 8 + 4 * mChunkIndex);
        } else {
            CHECK(mChunkOffsets64 != NULL);

            uint32_t entryCount = U32_AT(mChunkOffsets64->data() + 4);

            if (chunkIndex >= entryCount) {
            if (mChunkIndex >= entryCount) {
                mSampleIndex = mSampleCount;
                return;
            }

            mNextSampleOffset =
                U64_AT(mChunkOffsets64->data() + 8 + 8 * chunkIndex);
                U64_AT(mChunkOffsets64->data() + 8 + 8 * mChunkIndex);
        }
    }

@@ -194,14 +190,25 @@ void Parser::StaticTrackFragment::advance() {

    ++mSampleIndex;
    if (--mSampleToChunkRemaining == 0) {
        ++mChunkIndex;

        uint32_t entryCount = U32_AT(mSampleToChunk->data() + 4);

        if ((uint32_t)(mSampleToChunkIndex + 1) == entryCount) {
            mSampleIndex = mSampleCount;  // EOS.
            return;
        }
        // If this is the last entry in the sample to chunk table, we will
        // stay on this entry.
        if ((uint32_t)(mSampleToChunkIndex + 1) < entryCount) {
            uint32_t nextChunkIndex =
                U32_AT(mSampleToChunk->data() + 8 + 12 * (mSampleToChunkIndex + 1));

            CHECK_GE(nextChunkIndex, 1u);
            --nextChunkIndex;

            if (mChunkIndex >= nextChunkIndex) {
                CHECK_EQ(mChunkIndex, nextChunkIndex);
                ++mSampleToChunkIndex;
            }
        }

        mSampleToChunkRemaining =
            U32_AT(mSampleToChunk->data() + 8 + 12 * mSampleToChunkIndex + 4);
    }
@@ -216,46 +223,13 @@ static void setU32At(uint8_t *ptr, uint32_t x) {
    ptr[3] = x & 0xff;
}

void Parser::StaticTrackFragment::fixSampleToChunkTableIfNecessary() {
    if (mSampleToChunk == NULL) {
        return;
    }
    uint32_t entryCount = U32_AT(mSampleToChunk->data() + 4);
    uint32_t totalSamples = 0;
    for (uint32_t i = 0; i < entryCount; ++i) {
        totalSamples += U32_AT(mSampleToChunk->data() + 8 + 12 * i + 4);
    }

    if (totalSamples < mSampleCount) {
        // Some samples are not accounted for in the sample-to-chunk
        // data. Fabricate an extra chunk adjacent to the last one
        // in the table with the same sample desription index.

        ALOGW("Faking an extra sample-to-chunk entry for %d samples.",
              mSampleCount - totalSamples);

        uint32_t lastChunkIndex =
            U32_AT(mSampleToChunk->data() + 8 + 12 * (entryCount - 1));

        uint32_t lastSampleDescriptionIndex =
            U32_AT(mSampleToChunk->data() + 8 + 12 * (entryCount - 1) + 8);

        uint8_t *ptr = mSampleToChunk->data() + 8 + 12 * entryCount;

        setU32At(ptr, lastChunkIndex + 1);
        setU32At(ptr + 4, mSampleCount - totalSamples);
        setU32At(ptr + 8, lastSampleDescriptionIndex);
        setU32At(mSampleToChunk->data() + 4, entryCount + 1);
    }
}

status_t Parser::StaticTrackFragment::signalCompletion() {
    fixSampleToChunkTableIfNecessary();

    mSampleToChunkIndex = 0;

    mSampleToChunkRemaining = (mSampleToChunk == NULL) ? 0 :
        U32_AT(mSampleToChunk->data() + 8 + 12 * mSampleToChunkIndex + 4);
    mSampleToChunkRemaining =
        (mSampleToChunk == NULL)
            ? 0
            : U32_AT(mSampleToChunk->data() + 8 + 12 * mSampleToChunkIndex + 4);

    updateSampleInfo();

@@ -339,7 +313,7 @@ status_t Parser::StaticTrackFragment::parseSampleToChunk(
        return ERROR_MALFORMED;
    }

    parser->copyBuffer(&mSampleToChunk, offset, size, 12 /* extra */);
    parser->copyBuffer(&mSampleToChunk, offset, size);

    return OK;
}
+1 −1
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@ protected:
private:
    size_t mSampleIndex;
    size_t mSampleCount;
    uint32_t mChunkIndex;

    SampleInfo mSampleInfo;

@@ -112,7 +113,6 @@ private:
    uint64_t mNextSampleOffset;

    void updateSampleInfo();
    void fixSampleToChunkTableIfNecessary();

    DISALLOW_EVIL_CONSTRUCTORS(StaticTrackFragment);
};