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; }
__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; }