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

Commit 7878f087 authored by Lajos Molnar's avatar Lajos Molnar Committed by Gerrit Code Review
Browse files

Merge "stagefright: Fix seeking in MPEG4 container - do not merge"

parents 2e25819f c75fa318
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -3284,7 +3284,7 @@ status_t MPEG4Source::read(


        uint32_t sampleIndex;
        uint32_t sampleIndex;
        status_t err = mSampleTable->findSampleAtTime(
        status_t err = mSampleTable->findSampleAtTime(
                seekTimeUs * mTimescale / 1000000,
                seekTimeUs, 1000000, mTimescale,
                &sampleIndex, findFlags);
                &sampleIndex, findFlags);


        if (mode == ReadOptions::SEEK_CLOSEST) {
        if (mode == ReadOptions::SEEK_CLOSEST) {
+9 −5
Original line number Original line Diff line number Diff line
@@ -320,22 +320,26 @@ status_t MyVorbisExtractor::seekToTime(int64_t timeUs) {
    }
    }


    size_t left = 0;
    size_t left = 0;
    size_t right = mTableOfContents.size();
    size_t right_plus_one = mTableOfContents.size();
    while (left < right) {
    while (left < right_plus_one) {
        size_t center = left / 2 + right / 2 + (left & right & 1);
        size_t center = left + (right_plus_one - left) / 2;


        const TOCEntry &entry = mTableOfContents.itemAt(center);
        const TOCEntry &entry = mTableOfContents.itemAt(center);


        if (timeUs < entry.mTimeUs) {
        if (timeUs < entry.mTimeUs) {
            right = center;
            right_plus_one = center;
        } else if (timeUs > entry.mTimeUs) {
        } else if (timeUs > entry.mTimeUs) {
            left = center + 1;
            left = center + 1;
        } else {
        } else {
            left = right = center;
            left = center;
            break;
            break;
        }
        }
    }
    }


    if (left == mTableOfContents.size()) {
        --left;
    }

    const TOCEntry &entry = mTableOfContents.itemAt(left);
    const TOCEntry &entry = mTableOfContents.itemAt(left);


    ALOGV("seeking to entry %d / %d at offset %lld",
    ALOGV("seeking to entry %d / %d at offset %lld",
+78 −113
Original line number Original line Diff line number Diff line
@@ -520,83 +520,72 @@ void SampleTable::buildSampleEntriesTable() {
}
}


status_t SampleTable::findSampleAtTime(
status_t SampleTable::findSampleAtTime(
        uint32_t req_time, uint32_t *sample_index, uint32_t flags) {
        uint64_t req_time, uint64_t scale_num, uint64_t scale_den,
        uint32_t *sample_index, uint32_t flags) {
    buildSampleEntriesTable();
    buildSampleEntriesTable();


    uint32_t left = 0;
    uint32_t left = 0;
    uint32_t right = mNumSampleSizes;
    uint32_t right_plus_one = mNumSampleSizes;
    while (left < right) {
    while (left < right_plus_one) {
        uint32_t center = (left + right) / 2;
        uint32_t center = left + (right_plus_one - left) / 2;
        uint32_t centerTime = mSampleTimeEntries[center].mCompositionTime;
        uint64_t centerTime =
            getSampleTime(center, scale_num, scale_den);


        if (req_time < centerTime) {
        if (req_time < centerTime) {
            right = center;
            right_plus_one = center;
        } else if (req_time > centerTime) {
        } else if (req_time > centerTime) {
            left = center + 1;
            left = center + 1;
        } else {
        } else {
            left = center;
            *sample_index = mSampleTimeEntries[center].mSampleIndex;
            break;
            return OK;
        }
        }
    }
    }


    if (left == mNumSampleSizes) {
    uint32_t closestIndex = left;

    if (closestIndex == mNumSampleSizes) {
        if (flags == kFlagAfter) {
        if (flags == kFlagAfter) {
            return ERROR_OUT_OF_RANGE;
            return ERROR_OUT_OF_RANGE;
        }
        }

        flags = kFlagBefore;
        --left;
    } else if (closestIndex == 0) {
        if (flags == kFlagBefore) {
            // normally we should return out of range, but that is
            // treated as end-of-stream.  instead return first sample
            //
            // return ERROR_OUT_OF_RANGE;
        }
        flags = kFlagAfter;
    }
    }

    uint32_t closestIndex = left;


    switch (flags) {
    switch (flags) {
        case kFlagBefore:
        case kFlagBefore:
        {
        {
            while (closestIndex > 0
                    && mSampleTimeEntries[closestIndex].mCompositionTime
                            > req_time) {
            --closestIndex;
            --closestIndex;
            }
            break;
            break;
        }
        }


        case kFlagAfter:
        case kFlagAfter:
        {
        {
            while (closestIndex + 1 < mNumSampleSizes
            // nothing to do
                    && mSampleTimeEntries[closestIndex].mCompositionTime
                            < req_time) {
                ++closestIndex;
            }
            break;
            break;
        }
        }


        default:
        default:
        {
        {
            CHECK(flags == kFlagClosest);
            CHECK(flags == kFlagClosest);

            // pick closest based on timestamp. use abs_difference for safety
            if (closestIndex > 0) {
            if (abs_difference(
                // Check left neighbour and pick closest.
                    getSampleTime(closestIndex, scale_num, scale_den), req_time) >
                uint32_t absdiff1 =
                    abs_difference(
                            mSampleTimeEntries[closestIndex].mCompositionTime,
                            req_time);

                uint32_t absdiff2 =
                abs_difference(
                abs_difference(
                            mSampleTimeEntries[closestIndex - 1].mCompositionTime,
                    req_time, getSampleTime(closestIndex - 1, scale_num, scale_den))) {
                            req_time);
                --closestIndex;

                if (absdiff1 > absdiff2) {
                    closestIndex = closestIndex - 1;
                }
            }
            }

            break;
            break;
        }
        }
    }
    }


    *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex;
    *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex;

    return OK;
    return OK;
}
}


@@ -618,109 +607,85 @@ status_t SampleTable::findSyncSampleNear(
    }
    }


    uint32_t left = 0;
    uint32_t left = 0;
    uint32_t right = mNumSyncSamples;
    uint32_t right_plus_one = mNumSyncSamples;
    while (left < right) {
    while (left < right_plus_one) {
        uint32_t center = left + (right - left) / 2;
        uint32_t center = left + (right_plus_one - left) / 2;
        uint32_t x = mSyncSamples[center];
        uint32_t x = mSyncSamples[center];


        if (start_sample_index < x) {
        if (start_sample_index < x) {
            right = center;
            right_plus_one = center;
        } else if (start_sample_index > x) {
        } else if (start_sample_index > x) {
            left = center + 1;
            left = center + 1;
        } else {
        } else {
            left = center;
            *sample_index = x;
            break;
            return OK;
        }
        }
    }
    }

    if (left == mNumSyncSamples) {
    if (left == mNumSyncSamples) {
        if (flags == kFlagAfter) {
        if (flags == kFlagAfter) {
            ALOGE("tried to find a sync frame after the last one: %d", left);
            ALOGE("tried to find a sync frame after the last one: %d", left);
            return ERROR_OUT_OF_RANGE;
            return ERROR_OUT_OF_RANGE;
        }
        }
        left = left - 1;
        flags = kFlagBefore;
    }
    }
    else if (left == 0) {
        if (flags == kFlagBefore) {
            ALOGE("tried to find a sync frame before the first one: %d", left);


    // Now ssi[left] is the sync sample index just before (or at)
            // normally we should return out of range, but that is
    // start_sample_index.
            // treated as end-of-stream.  instead seek to first sync
    // Also start_sample_index < ssi[left + 1], if left + 1 < mNumSyncSamples.
            //

            // return ERROR_OUT_OF_RANGE;
    uint32_t x = mSyncSamples[left];
        }

        flags = kFlagAfter;
    if (left + 1 < mNumSyncSamples) {
    }
        uint32_t y = mSyncSamples[left + 1];


        // our sample lies between sync samples x and y.
    // Now ssi[left - 1] <(=) start_sample_index <= ssi[left]
    switch (flags) {
        case kFlagBefore:
        {
            --left;
            break;
        }
        case kFlagAfter:
        {
            // nothing to do
            break;
        }
        default:
        {
            // this route is not used, but implement it nonetheless
            CHECK(flags == kFlagClosest);


            status_t err = mSampleIterator->seekTo(start_sample_index);
            status_t err = mSampleIterator->seekTo(start_sample_index);
            if (err != OK) {
            if (err != OK) {
                return err;
                return err;
            }
            }

            uint32_t sample_time = mSampleIterator->getSampleTime();
            uint32_t sample_time = mSampleIterator->getSampleTime();


        err = mSampleIterator->seekTo(x);
            err = mSampleIterator->seekTo(mSyncSamples[left]);
            if (err != OK) {
            if (err != OK) {
                return err;
                return err;
            }
            }
        uint32_t x_time = mSampleIterator->getSampleTime();
            uint32_t upper_time = mSampleIterator->getSampleTime();


        err = mSampleIterator->seekTo(y);
            err = mSampleIterator->seekTo(mSyncSamples[left - 1]);
            if (err != OK) {
            if (err != OK) {
                return err;
                return err;
            }
            }
            uint32_t lower_time = mSampleIterator->getSampleTime();


        uint32_t y_time = mSampleIterator->getSampleTime();
            // use abs_difference for safety

            if (abs_difference(upper_time, sample_time) >
        if (abs_difference(x_time, sample_time)
                abs_difference(sample_time, lower_time)) {
                > abs_difference(y_time, sample_time)) {
                --left;
            // Pick the sync sample closest (timewise) to the start-sample.
            x = y;
            ++left;
        }
    }

    switch (flags) {
        case kFlagBefore:
        {
            if (x > start_sample_index) {
                CHECK(left > 0);

                x = mSyncSamples[left - 1];

                if (x > start_sample_index) {
                    // The table of sync sample indices was not sorted
                    // properly.
                    return ERROR_MALFORMED;
                }
            }
            break;
        }

        case kFlagAfter:
        {
            if (x < start_sample_index) {
                if (left + 1 >= mNumSyncSamples) {
                    return ERROR_OUT_OF_RANGE;
                }

                x = mSyncSamples[left + 1];

                if (x < start_sample_index) {
                    // The table of sync sample indices was not sorted
                    // properly.
                    return ERROR_MALFORMED;
                }
            }
            }

            break;
            break;
        }
        }

        default:
            break;
    }
    }


    *sample_index = x;
    *sample_index = mSyncSamples[left];

    return OK;
    return OK;
}
}


+9 −1
Original line number Original line Diff line number Diff line
@@ -74,7 +74,8 @@ public:
        kFlagClosest
        kFlagClosest
    };
    };
    status_t findSampleAtTime(
    status_t findSampleAtTime(
            uint32_t req_time, uint32_t *sample_index, uint32_t flags);
            uint64_t req_time, uint64_t scale_num, uint64_t scale_den,
            uint32_t *sample_index, uint32_t flags);


    status_t findSyncSampleNear(
    status_t findSyncSampleNear(
            uint32_t start_sample_index, uint32_t *sample_index,
            uint32_t start_sample_index, uint32_t *sample_index,
@@ -137,6 +138,13 @@ private:


    friend struct SampleIterator;
    friend struct SampleIterator;


    // normally we don't round
    inline uint64_t getSampleTime(
            size_t sample_index, uint64_t scale_num, uint64_t scale_den) const {
        return (mSampleTimeEntries[sample_index].mCompositionTime
            * scale_num) / scale_den;
    }

    status_t getSampleSize_l(uint32_t sample_index, size_t *sample_size);
    status_t getSampleSize_l(uint32_t sample_index, size_t *sample_size);
    uint32_t getCompositionTimeOffset(uint32_t sampleIndex);
    uint32_t getCompositionTimeOffset(uint32_t sampleIndex);