Esempio n. 1
0
STDMETHODIMP_(long) IDSMChapterBagImpl::ChapLookup(REFERENCE_TIME* prt, BSTR* ppName)
{
	CheckPointer(prt, -1);

	ChapSort();

	int i = range_bsearch(m_chapters, *prt);
	if(i < 0) return -1;

	*prt = m_chapters[i].rt;
	if(ppName) *ppName = m_chapters[i].name.AllocSysString();

	return i;
}
Esempio n. 2
0
__int64 CDSMSplitterFile::FindSyncPoint(REFERENCE_TIME rt)
{
	if (/*!m_sps.IsEmpty()*/ m_sps.GetCount() > 1) {
		int i = range_bsearch(m_sps, m_rtFirst + rt);
		return i >= 0 ? m_sps[i].fp : 0;
	}

	if (m_rtDuration <= 0 || rt <= m_rtFirst) {
		return 0;
	}

	// ok, do the hard way then

	dsmp_t type;
	UINT64 syncpos, len;

	// 1. find some boundaries close to rt's position (minpos, maxpos)

	__int64 minpos = 0, maxpos = GetLength();

	for (int i = 0; i < 10 && (maxpos - minpos) >= 1024*1024; i++) {
		Seek((minpos + maxpos) / 2);

		while (GetPos() < maxpos) {
			if (!Sync(syncpos, type, len)) {
				continue;
			}

			__int64 pos = GetPos();

			if (type == DSMP_SAMPLE) {
				Packet p;
				if (Read(len, &p, false) && p.rtStart != Packet::INVALID_TIME) {
					REFERENCE_TIME dt = (p.rtStart -= m_rtFirst) - rt;
					if (dt >= 0) {
						maxpos = max((__int64)syncpos - 65536, minpos);
					} else {
						minpos = syncpos;
					}
					break;
				}
			}

			Seek(pos + len);
		}
	}

	// 2. find the first packet just after rt (maxpos)

	Seek(minpos);

	while (GetRemaining()) {
		if (!Sync(syncpos, type, len)) {
			continue;
		}

		__int64 pos = GetPos();

		if (type == DSMP_SAMPLE) {
			Packet p;
			if (Read(len, &p, false) && p.rtStart != Packet::INVALID_TIME) {
				REFERENCE_TIME dt = (p.rtStart -= m_rtFirst) - rt;
				if (dt >= 0) {
					maxpos = (__int64)syncpos;
					break;
				}
			}
		}

		Seek(pos + len);
	}

	// 3. iterate backwards from maxpos and find at least one syncpoint for every stream, except for subtitle streams

	CAtlMap<BYTE,BYTE> ids;

	{
		POSITION pos = m_mts.GetStartPosition();
		while (pos) {
			BYTE id;
			CMediaType mt;
			m_mts.GetNextAssoc(pos, id, mt);
			if (mt.majortype != MEDIATYPE_Text && mt.majortype != MEDIATYPE_Subtitle) {
				ids[id] = 0;
			}
		}
	}

	__int64 ret = maxpos;

	while (maxpos > 0 && !ids.IsEmpty()) {
		minpos = max(0, maxpos - 65536);

		Seek(minpos);

		while (Sync(syncpos, type, len) && GetPos() < maxpos) {
			UINT64 pos = GetPos();

			if (type == DSMP_SAMPLE) {
				Packet p;
				if (Read(len, &p, false) && p.rtStart != Packet::INVALID_TIME && p.bSyncPoint) {
					BYTE id = (BYTE)p.TrackNumber, tmp;
					if (ids.Lookup(id, tmp)) {
						ids.RemoveKey((BYTE)p.TrackNumber);
						ret = min(ret, (__int64)syncpos);
					}
				}
			}

			Seek(pos + len);
		}

		maxpos = minpos;
	}

	return ret;
}