Tuesday, May 16, 2006

pre-fetching video


bool CPlaylistDlg::PreFetchVideo()
{
CAviToBmp vid;
for (int i = 0; i < BANKS; i++) {
int count = m_Bank[i].GetSize();
for (int j = 0; j < count; j++) {
LPCSTR Path = m_Bank[i][j].m_Path;
if (IsVideo(Path)) {
if (!vid.Open(Path))
return(FALSE);
}
}
}
return(TRUE);
}

This takes approx. 10 seconds for all 340 clips. We can't pre-open the clips because AVIStreamGetFrameOpen won't open more than 75 AVI files simultaneously (it fails with no error message). Not sure why just opening and closing the clips helps. Something to do with disk caching? Not sure how *much* it helps either.

The 10 second delay can be avoided by doing the pre-fetch in a background thread. Note the CoInitialize! AviFileOpen fails without it. This gives me a bad feeling that VfW isn't thread-safe...

UINT CPlaylistDlg::PreFetchVideoThread(LPVOID pParam)
{
CoInitialize(0);
CPlaylistDlg *pd = (CPlaylistDlg *)pParam;
if (!pd->PreFetchVideo())
AfxMessageBox("Can't pre-fetch video");
CoUninitialize();
return(0);
}

in CPlaylistDlg::Cache:
AfxBeginThread(PreFetchVideoThread, this,
THREAD_PRIORITY_BELOW_NORMAL, 0, 0, 0);

The 75 clip limit is apparently NOT due to XVID, it occurs with Cinepack too.

Test to determine how much of Open delay is due to AVIStreamGetFrameOpen. Result for 100 Opens:

total avg min max
Open 4.915 .049 .007 .087
GetFr. 0.790 .008 .007 .009

A second run gave very similar results:

Open 3.119 .031 .007 .087
GetFr. 0.741 .007 .007 .009

Result: AVIStreamGetFrameOpen is less than 15% of the average, but more importantly, it has a static cost of ~8 milliseconds. This makes a reasonable case for trying the partial pre-open strategy (pre-open all clips but without doing AVIStreamGetFrameOpen, and then do AVIStreamGetFrameOpen when the clip is selected).

No comments: