Пример #1
0
void 
DurationIndex::AppendCTTSMode(REFERENCE_TIME tStart, REFERENCE_TIME tEnd)
{
	// if the frames are out of order and the end time is invalid,
	// we must use the frame rate to work out the difference
	REFERENCE_TIME dur;
	if (m_bUseFrameRate)
	{
		dur = m_tFrame;
	}
	else
	{
		 dur = (tEnd - tStart);
	}
	// ToScale will round down, and this truncation causes the 
	// diff between decode and presentation time to get larger and larger
	// so we sum both reference time and scaled totals and use the difference. 
	// That way the rounding error does not build up.
	// the simpler version of these two lines is: cThis = long(ToScale(tEnd - tStart));
	m_refDuration += dur;
	long cThis = long(ToScale(m_refDuration) - m_TotalDuration);

	// difference between sum of durations to here and actual CTS
	// -- note: do this before adding current sample to total duration
	long cDiff =  long(ToScale(tStart) - m_TotalDuration);

	AddDuration(cThis);

	m_CTTS.Append(cDiff);
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
void
DurationIndex::ModeDecide()
{
	if (m_nSamples > 0)
	{
		bool bReverse = false;
		bool bDurOk = true;
		LONGLONG ave = m_SumDurations / m_nSamples;

		// 70fps is the maximum reasonable frame rate, so anything less than this is
		// likely to be an error
		const REFERENCE_TIME min_frame_dur = (UNITS / 70);
		if (ave < min_frame_dur)
		{
			bDurOk = false;
		}

		// in the most common case, when converting from TS output, we don't
		// get either accurate end times or an accuration rate in the media type.
		// The smallest positive interval between frames should be the frame duration.
		REFERENCE_TIME tInterval = 0;

		for (int i = 0; i < m_nSamples; i++)
		{
			if (i > 0)
			{
				if (m_SampleStarts[i] < m_SampleStarts[i-1])
				{
					bReverse = true;
				}
				else 
				{
					REFERENCE_TIME tThis = m_SampleStarts[i] - m_SampleStarts[i-1];
					if (tThis > min_frame_dur)
					{
						if ((tInterval == 0) || (tThis < tInterval))
						{
							tInterval = tThis;
						}
					}
				}
			}
		}
		m_tStartFirst = m_SampleStarts[0];

		// this interval is a better guess than the media type frame rate
		if (tInterval > min_frame_dur)
		{
			m_tFrame = tInterval;
		}

		if (bReverse)
		{
			m_bCTTS = true;

			if (!bDurOk)
			{
				m_bUseFrameRate = true;
			}
			else
			{
				m_bUseFrameRate = false;
			}

			// remember that the first frame might not be zero
			m_TotalDuration = ToScale(m_tStartFirst);
			m_refDuration = m_tStartFirst;
			for (int i = 0; i < m_nSamples; i++)
			{
				AppendCTTSMode(m_SampleStarts[i], m_SampleStops[i]);
			}
		}
		else
		{
			m_bCTTS = false;
			m_TotalDuration = ToScale(m_tStartFirst);
			for (int i = 1; i < m_nSamples; i++)
			{
				AddDuration(long(ToScale(m_SampleStarts[i]) - m_TotalDuration));
			}
		}
	}
}