示例#1
0
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;
}