Граф фильтра DirectShow периодически кодирует «неподвижный» MP4 с проблемами временного кода - PullRequest
0 голосов
/ 24 апреля 2019

Я использую DirectShow для кодирования MP4 в режиме реального времени из источника с веб-камеры. Я использую кодировщик Intel QuickSync для кодирования h264, а также их фильтр Muxing, все они подключены к стандартному File Writer.

Большую часть времени видео получаются великолепными - без проблем. Однако, похоже, существует условие состязания, при котором иногда создаваемые файлы выглядят так, как будто они являются неподвижными кадрами при открытии в WMP или VLC, но фактически вся информация, по-видимому, присутствует, поскольку их можно легко перекодировать для восстановления. - практически любой метод перекодировки, который я пробовал, делает свое дело.

Хотя перекодирование работает, я бы хотел решить проблему в источнике, а не удваивать работу.

Кто-нибудь сталкивался с этим раньше, чтобы дать представление о том, что может быть причиной проблемы? Я включу некоторый код, который я использую, чтобы остановить график, поскольку я предполагаю, что именно здесь вводится условие гонки.

Я пытался использовать методы Stop () и StopWhenReady () IMediaControl, с одинаковыми результатами. Я попытался проверить, не заблокирован ли файл перед возвратом из этого метода, но он никогда не блокируется после остановки, а также попытался выполнить кодирование с несколькими различными настройками качества.

int hr = 0;
IBaseFilter outputSampleGrabberFilter = null;
FilterState filterState;

try
{
    IMediaControl mediaCtrl = filterGraph as IMediaControl;

    hr = filterGraph.FindFilterByName(FilterIdentifier.OUTPUT_SAMPLE_GRABBER.ToString(),
        out outputSampleGrabberFilter);
    DsError.ThrowExceptionForHR(hr);
    ISampleGrabber outputSampleGrabber = outputSampleGrabberFilter as ISampleGrabber;

    hr = outputSampleGrabber.SetCallback(null, 0);
    DsError.ThrowExceptionForHR(hr);

    hr = mediaCtrl.Pause();
    DsError.ThrowExceptionForHR(hr);

    while (filterState != FilterState.Paused)
    {
        hr = mediaCtrl.GetState(100, out filterState);
        DsError.ThrowExceptionForHR(hr);
    }

    hr = mediaCtrl.StopWhenReady();
    DsError.ThrowExceptionForHR(hr);

    hr = mediaCtrl.GetState(100, out filterState);
    DsError.ThrowExceptionForHR(hr);

    while (filterState != FilterState.Stopped)
    {
        hr = mediaCtrl.GetState(100, out filterState);
        DsError.ThrowExceptionForHR(hr);
    }       
}
finally
{
    DisposeComObject(ref outputSampleGrabberFilter);
}
...