summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/libstagefright/MPEG4Extractor.cpp2
-rw-r--r--media/libstagefright/OggExtractor.cpp14
-rw-r--r--media/libstagefright/SampleTable.cpp191
-rw-r--r--media/libstagefright/include/SampleTable.h10
-rw-r--r--media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp7
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;
}