void aiContext::getTimeSampling(int i, aiTimeSamplingData& dst) { auto ts = m_archive.getTimeSampling(i); auto tst = ts->getTimeSamplingType(); dst.numTimes = (int)ts->getNumStoredTimes(); if (tst.isUniform() || tst.isCyclic()) { int numCycles = int(m_archive.getMaxNumSamplesForTimeSamplingIndex(i) / tst.getNumSamplesPerCycle()); dst.type = tst.isUniform() ? aiTimeSamplingType_Uniform : aiTimeSamplingType_Cyclic; dst.interval = (float)tst.getTimePerCycle(); dst.startTime = (float)ts->getStoredTimes()[0]; dst.endTime = dst.startTime + dst.interval * (numCycles - 1); dst.numTimes = (int)ts->getNumStoredTimes(); dst.times = const_cast<double*>(&ts->getStoredTimes()[0]); } else if (tst.isAcyclic()) { dst.type = aiTimeSamplingType_Acyclic; dst.startTime = (float)ts->getSampleTime(0); dst.endTime = (float)ts->getSampleTime(ts->getNumStoredTimes() - 1); dst.numTimes = (int)ts->getNumStoredTimes(); dst.times = const_cast<double*>(&ts->getStoredTimes()[0]); } }
status_t SampleTable::findSampleAtTime( uint64_t req_time, uint64_t scale_num, uint64_t scale_den, uint32_t *sample_index, uint32_t flags) { buildSampleEntriesTable(); if (mSampleTimeEntries == NULL) { return ERROR_OUT_OF_RANGE; } 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); if (req_time < centerTime) { right_plus_one = center; } else if (req_time > centerTime) { left = center + 1; } else { *sample_index = mSampleTimeEntries[center].mSampleIndex; return OK; } } uint32_t closestIndex = left; if (closestIndex == 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; } switch (flags) { case kFlagBefore: { --closestIndex; break; } case kFlagAfter: { // nothing to do 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; } break; } } *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex; return OK; }