diff options
-rw-r--r-- | media/libstagefright/MPEG4Extractor.cpp | 2 | ||||
-rw-r--r-- | media/libstagefright/OggExtractor.cpp | 14 | ||||
-rw-r--r-- | media/libstagefright/SampleTable.cpp | 191 | ||||
-rw-r--r-- | media/libstagefright/include/SampleTable.h | 10 | ||||
-rw-r--r-- | media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp | 7 |
5 files changed, 123 insertions, 101 deletions
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp index 7d3a838..362cd6b 100644 --- a/media/libstagefright/MPEG4Extractor.cpp +++ b/media/libstagefright/MPEG4Extractor.cpp @@ -3284,7 +3284,7 @@ status_t MPEG4Source::read( uint32_t sampleIndex; status_t err = mSampleTable->findSampleAtTime( - seekTimeUs, 1000000, mTimescale, + seekTimeUs * mTimescale / 1000000, &sampleIndex, findFlags); if (mode == ReadOptions::SEEK_CLOSEST) { diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp index 1965ef9..f3eeb03 100644 --- a/media/libstagefright/OggExtractor.cpp +++ b/media/libstagefright/OggExtractor.cpp @@ -320,26 +320,22 @@ status_t MyVorbisExtractor::seekToTime(int64_t timeUs) { } size_t left = 0; - size_t right_plus_one = mTableOfContents.size(); - while (left < right_plus_one) { - size_t center = left + (right_plus_one - left) / 2; + size_t right = mTableOfContents.size(); + while (left < right) { + size_t center = left / 2 + right / 2 + (left & right & 1); const TOCEntry &entry = mTableOfContents.itemAt(center); if (timeUs < entry.mTimeUs) { - right_plus_one = center; + right = center; } else if (timeUs > entry.mTimeUs) { left = center + 1; } else { - left = center; + left = right = center; break; } } - if (left == mTableOfContents.size()) { - --left; - } - const TOCEntry &entry = mTableOfContents.itemAt(left); ALOGV("seeking to entry %d / %d at offset %lld", diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp index 318555e..d9858d7 100644 --- a/media/libstagefright/SampleTable.cpp +++ b/media/libstagefright/SampleTable.cpp @@ -520,72 +520,83 @@ void SampleTable::buildSampleEntriesTable() { } status_t SampleTable::findSampleAtTime( - uint64_t req_time, uint64_t scale_num, uint64_t scale_den, - uint32_t *sample_index, uint32_t flags) { + uint32_t req_time, uint32_t *sample_index, uint32_t flags) { buildSampleEntriesTable(); uint32_t left = 0; - uint32_t right_plus_one = mNumSampleSizes; - while (left < right_plus_one) { - uint32_t center = left + (right_plus_one - left) / 2; - uint64_t centerTime = - getSampleTime(center, scale_num, scale_den); + uint32_t right = mNumSampleSizes; + while (left < right) { + uint32_t center = (left + right) / 2; + uint32_t centerTime = mSampleTimeEntries[center].mCompositionTime; if (req_time < centerTime) { - right_plus_one = center; + right = center; } else if (req_time > centerTime) { left = center + 1; } else { - *sample_index = mSampleTimeEntries[center].mSampleIndex; - return OK; + left = center; + break; } } - uint32_t closestIndex = left; - - if (closestIndex == mNumSampleSizes) { + if (left == mNumSampleSizes) { if (flags == kFlagAfter) { return ERROR_OUT_OF_RANGE; } - flags = kFlagBefore; - } 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; + + --left; } + uint32_t closestIndex = left; + switch (flags) { case kFlagBefore: { - --closestIndex; + while (closestIndex > 0 + && mSampleTimeEntries[closestIndex].mCompositionTime + > req_time) { + --closestIndex; + } break; } case kFlagAfter: { - // nothing to do + while (closestIndex + 1 < mNumSampleSizes + && mSampleTimeEntries[closestIndex].mCompositionTime + < req_time) { + ++closestIndex; + } break; } default: { CHECK(flags == kFlagClosest); - // pick closest based on timestamp. use abs_difference for safety - if (abs_difference( - getSampleTime(closestIndex, scale_num, scale_den), req_time) > - abs_difference( - req_time, getSampleTime(closestIndex - 1, scale_num, scale_den))) { - --closestIndex; + + if (closestIndex > 0) { + // Check left neighbour and pick closest. + uint32_t absdiff1 = + abs_difference( + mSampleTimeEntries[closestIndex].mCompositionTime, + req_time); + + uint32_t absdiff2 = + abs_difference( + mSampleTimeEntries[closestIndex - 1].mCompositionTime, + req_time); + + if (absdiff1 > absdiff2) { + closestIndex = closestIndex - 1; + } } + break; } } *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex; + return OK; } @@ -607,85 +618,109 @@ status_t SampleTable::findSyncSampleNear( } uint32_t left = 0; - uint32_t right_plus_one = mNumSyncSamples; - while (left < right_plus_one) { - uint32_t center = left + (right_plus_one - left) / 2; + uint32_t right = mNumSyncSamples; + while (left < right) { + uint32_t center = left + (right - left) / 2; uint32_t x = mSyncSamples[center]; if (start_sample_index < x) { - right_plus_one = center; + right = center; } else if (start_sample_index > x) { left = center + 1; } else { - *sample_index = x; - return OK; + left = center; + break; } } - if (left == mNumSyncSamples) { if (flags == kFlagAfter) { ALOGE("tried to find a sync frame after the last one: %d", left); return ERROR_OUT_OF_RANGE; } - flags = kFlagBefore; + left = left - 1; } - else if (left == 0) { - if (flags == kFlagBefore) { - ALOGE("tried to find a sync frame before the first one: %d", left); - // normally we should return out of range, but that is - // treated as end-of-stream. instead seek to first sync - // - // return ERROR_OUT_OF_RANGE; + // Now ssi[left] is the sync sample index just before (or at) + // start_sample_index. + // Also start_sample_index < ssi[left + 1], if left + 1 < mNumSyncSamples. + + uint32_t x = mSyncSamples[left]; + + if (left + 1 < mNumSyncSamples) { + uint32_t y = mSyncSamples[left + 1]; + + // our sample lies between sync samples x and y. + + status_t err = mSampleIterator->seekTo(start_sample_index); + if (err != OK) { + return err; + } + + uint32_t sample_time = mSampleIterator->getSampleTime(); + + err = mSampleIterator->seekTo(x); + if (err != OK) { + return err; + } + uint32_t x_time = mSampleIterator->getSampleTime(); + + err = mSampleIterator->seekTo(y); + if (err != OK) { + return err; + } + + uint32_t y_time = mSampleIterator->getSampleTime(); + + if (abs_difference(x_time, sample_time) + > abs_difference(y_time, sample_time)) { + // Pick the sync sample closest (timewise) to the start-sample. + x = y; + ++left; } - flags = kFlagAfter; } - // 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); + if (x > start_sample_index) { + CHECK(left > 0); - status_t err = mSampleIterator->seekTo(start_sample_index); - if (err != OK) { - return err; - } - uint32_t sample_time = mSampleIterator->getSampleTime(); + x = mSyncSamples[left - 1]; - err = mSampleIterator->seekTo(mSyncSamples[left]); - if (err != OK) { - return err; + if (x > start_sample_index) { + // The table of sync sample indices was not sorted + // properly. + return ERROR_MALFORMED; + } } - uint32_t upper_time = mSampleIterator->getSampleTime(); + break; + } - err = mSampleIterator->seekTo(mSyncSamples[left - 1]); - if (err != OK) { - return err; + 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; + } } - uint32_t lower_time = mSampleIterator->getSampleTime(); - // use abs_difference for safety - if (abs_difference(upper_time, sample_time) > - abs_difference(sample_time, lower_time)) { - --left; - } break; } + + default: + break; } - *sample_index = mSyncSamples[left]; + *sample_index = x; + return OK; } diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h index ed91adc..847dff7 100644 --- a/media/libstagefright/include/SampleTable.h +++ b/media/libstagefright/include/SampleTable.h @@ -74,8 +74,7 @@ public: kFlagClosest }; status_t findSampleAtTime( - uint64_t req_time, uint64_t scale_num, uint64_t scale_den, - uint32_t *sample_index, uint32_t flags); + uint32_t req_time, uint32_t *sample_index, uint32_t flags); status_t findSyncSampleNear( uint32_t start_sample_index, uint32_t *sample_index, @@ -138,13 +137,6 @@ private: 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); uint32_t getCompositionTimeOffset(uint32_t sampleIndex); diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp index 20a7076..eb9fcf7 100644 --- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp +++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp @@ -177,19 +177,18 @@ OMX_ERRORTYPE SoftVideoDecoderOMXComponent::internalGetParameter( { OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel = (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) params; - OMX_U32 profileIndex = profileLevel->nProfileIndex; if (profileLevel->nPortIndex != kInputPortIndex) { ALOGE("Invalid port index: %" PRIu32, profileLevel->nPortIndex); return OMX_ErrorUnsupportedIndex; } - if (profileIndex >= mNumProfileLevels) { + if (index >= mNumProfileLevels) { return OMX_ErrorNoMore; } - profileLevel->eProfile = mProfileLevels[profileIndex].mProfile; - profileLevel->eLevel = mProfileLevels[profileIndex].mLevel; + profileLevel->eProfile = mProfileLevels[index].mProfile; + profileLevel->eLevel = mProfileLevels[index].mLevel; return OMX_ErrorNone; } |