Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
[Функция, связанная с этой страницей, DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngineи аудио и видеозахват в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует использовать новый код MediaPlayer, IMFMediaEngine и аудио-видеозахват в Media Foundation вместо DirectShowпо возможности. Корпорация Майкрософт предлагает, что существующий код, использующий устаревшие API, будет перезаписан для использования новых API, если это возможно.]
Чтобы записать файл, просто запустите граф фильтра, вызвав метод IMediaControl::Run. Дождитесь завершения воспроизведения и явного остановки графа путем вызова IMediaControl::Stop; в противном случае файл написан неправильно.
Чтобы отобразить ход выполнения операции записи файлов, запросите фильтр Mux для интерфейса IMediaSeeking. Вызовите метод IMediaSeeking::GetDuration, чтобы получить длительность файла. Периодически во время выполнения графа вызовите метод IMediaSeeking::GetCurrentPosition, чтобы получить текущую позицию графа в потоке. Текущая позиция, разделенная на продолжительность, определяет процент завершения.
Заметка
Приложение обычно запрашивает диспетчер графов фильтров для IMediaSeeking, но запись файлов является исключением из этого правила. Диспетчер графов фильтров вычисляет текущую позицию из начальной позиции и как долго граф работает, что является точным для воспроизведения файлов, но не для записи данных. Таким образом, чтобы получить точный результат, необходимо получить позицию из фильтра MUX.
Следующий код получает длительность файла, запускает таймер для обновления пользовательского интерфейса приложения и запускает граф фильтра. (Проверка ошибок опущена для ясности.)
IMediaSeeking *pSeek = NULL;
IMediaEventEx *pEvent = NULL;
IMediaControl *pControl = NULL;
REFERENCE_TIME rtTotal;
// Query for interfaces. Remember to release them later.
hr = pMux->QueryInterface(IID_IMediaSeeking, (void**)&pSeek);
hr = pGraph->QueryInterface(IID_IMediaEventEx, (void**)&pEvent);
hr = pGraph->QueryInterface(IID_IMediaControl, (void**)&pControl);
// Error checking is omitted for clarity.
// Set the DirectShow event notification window.
hr = pEvent->SetNotifyWindow((OAHWND)hwnd, WM_GRAPHNOTIFY, 0);
// Set the range of the progress bar to the file length (in seconds).
hr = pSeek->GetDuration(&rtTotal);
SendDlgItemMessage(hwnd, IDC_PROGRESS1, PBM_SETRANGE, 0,
MAKELPARAM(0, rtTotal / 10000000));
// Start the timer.
UINT_PTR res = SetTimer(hwnd, nIDEvent, 100, NULL);
// Run the graph.
pControl->Run();
Когда приложение получает событие таймера, оно может обновить пользовательский интерфейс с текущей позицией:
void OnTimer(HWND hDlg, IMediaSeeking *pSeek)
{
REFERENCE_TIME rtNow;
HRESULT hr = pSeek->GetCurrentPosition(&rtNow);
if (SUCCEEDED(hr))
{
SendDlgItemMessage(hDlg, IDC_PROGRESS1, PBM_SETPOS, rtNow/10000000, 0);
}
}
Когда приложение получает событие завершения DirectShow, оно должно остановить граф, как показано в следующем коде:
// Application window procedure
LRESULT CALLBACK WndProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
/* ... */
case WM_GRAPHNOTIFY:
DoHandleEvent();
break;
/* ... */
}
}
void DoHandleEvent()
{
long evCode, param1, param2;
bool bComplete = false;
if (!pEvent) return;
// Get all the events, and see we're done.
while (SUCCEEDED(pEvent->GetEvent(&evCode, ¶m1, ¶m2, 0))
{
pEvent->FreeEventParams(evCode, param1, param2);
switch(evCode)
{
case EC_USERABORT:
case EC_ERRORABORT:
case EC_COMPLETE:
bComplete = true;
break;
}
}
if (bComplete)
{
pControl->Stop(); // Important! You must stop the graph!
// Turn off event notification.
pEvent->SetNotifyWindow(NULL, 0, 0);
pEvent->Release();
pEvent = NULL;
// Reset the progress bar to zero and get rid of the timer.
SendDlgItemMessage(IDC_PROGRESS1, PBM_SETPOS, 0, 0);
KillTimer(hwnd, nIDEvent);
}
}