void DurationIndex::Add(REFERENCE_TIME tStart, REFERENCE_TIME tEnd) { // In general it is safer to just use the start time of each sample // since the stop time will be either wrong, or will just be deduced from // the next sample start time. // However, when frame re-ordering is happening, the composition time (== PTS) will // not be the same as the decode time (== DTS) and we need to use both start and // stop time to build the CTTS table. // We save the first few timestamps and then decide which mode to be in. if (m_nSamples < mode_decide_count) { if (m_nSamples == 0) { m_SumDurations = 0; } m_SumDurations += (tEnd - tStart); m_SampleStarts[m_nSamples] = tStart; m_SampleStops[m_nSamples] = tEnd; m_nSamples++; return; } else if (m_nSamples == mode_decide_count) { // this decides on a mode and then processes // all the samples in the table ModeDecide(); } if (m_bCTTS) { AppendCTTSMode(tStart, tEnd); } else { AddDuration(long(ToScale(tStart) - m_TotalDuration)); } m_nSamples++; m_tStartLast = tStart; m_tStopLast = tEnd; return; }
HRESULT DurationIndex::WriteTable(Atom* patm) { // do nothing if no samples at all HRESULT hr = S_OK; if (m_nSamples <= mode_decide_count) { ModeDecide(); } if (m_nSamples > 0) { if (!m_bCTTS) { // the final sample duration has not been recorded -- use the // stop time if (ToScale(m_tStopLast) > m_TotalDuration) { AddDuration(long(ToScale(m_tStopLast) - m_TotalDuration)); } else // NOTE: We still need some duration recorded, to avoid stts/stsz discrepancy at the very least AddDuration(1); } // create atom and write table smart_ptr<Atom> pstts = patm->CreateAtom('stts'); m_STTS.Write(pstts); pstts->Close(); if (m_bCTTS) { // write CTTS table smart_ptr<Atom> pctts = patm->CreateAtom('ctts'); m_CTTS.Write(pctts); pctts->Close(); } } return hr; }