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

Commit b9787142 authored by Andreas Huber's avatar Andreas Huber
Browse files

Fix static sample table processing, add support for h.263 video.

Change-Id: I5628d3437b5e6f8836d78557fd07ab87e5a914e3
parent 0d27c65d
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);
};