Наш ответ Чемберлену. На форуме Doom9 был такой пост: [QUOTE=mark0077;1371058]For those guys working on fullscreen options, I beg of you to improve this, to read the frame rate of the content, not from the media info, but from whatever is input from external filters. Until then, it is not usable if anything like de-interlacing is used, or if frame rate changes are introduced by external filters. I don't think it should be difficult as this frame rate is already used and displayed by the renderers obviously.[/QUOTE] Если более конкретно, то почему не работает автосмена частоты при использовании Reclock. Деинтерлейсинг на самом деле тут не причем. При деинтерлейсинге получается кратная частота. Пришлось детально разбираться, какие методы определения FPS есть в программе. Такое разное FPS. Сначала предлагаю посмотреть небольшой ролик, на примере которого буду детально рассказывать о методах определения FPS в MPC-HC. http://www.youtube.com/watch?v=nv2vruH5fcI Главное, что хочется сказать в первую очередь - все методы измерения FPS в DirectShow Output являются "пассивными". 1.Первый способ. [URL=http://img705.imageshack.us/i/fps1m.png/][IMG]http://img705.imageshack.us/img705/8117/fps1m.th.png[/IMG][/URL] Метод измерения FPS является простым статистическим. Описан в процедуре CDX9AllocatorPresenter::CalculateJitter() Значения измеренной FPS записываются в переменную m_fAvrFps. Особо не вникал, но, кажется, используется только для вывода статистики. И, по-моему, именно она используется в окне статистики, вызываемом по CTRL+4. Ее сильно глючит, зачастую показывает значения далекие от реальных. А при начале просмотра фильма показывает просто фантастические значения. 2.Второй способ. [URL=http://img251.imageshack.us/i/fps2.png/][IMG]http://img251.imageshack.us/img251/5853/fps2.th.png[/IMG][/URL] Метод основан на считывании данных из Pin. Данные о FPS туда должен закидывать декодер. Значения FPS записываются в переменную m_fps и получаются так: Сначала вытаскивается значение средней длительности кадра в сотнях наносекунд [code] if (SUCCEEDED (m_pOuterEVR->FindPin(L"VMR Input0", &pPin)) && SUCCEEDED (pPin->ConnectionMediaType(&mt)) ) { ExtractAvgTimePerFrame (&mt, m_rtTimePerFrame); } [/code] А потом производится деление [code] m_fps = 10000000.0 / m_rtTimePerFrame; [/code] Для того, чтобы программа не падала при делении на ноль, перед ним ставится дефолтное значение m_rtTimePerFrame: [code] // If framerate not set by Video Decoder choose 23.97... if (m_rtTimePerFrame == 0) m_rtTimePerFrame = 417166; [/code] С этим и связаны определенные глюки, о которых позже, но это все же лучше чем, падение программы. Этот метод работает быстро, т.к. не основан на статистике и данные получаются напрямую из декодера, показания не скачут. Значения вычисленные этим методом используются для синхронизации субтитров при проигрывании видеофайлов. Метод является универсальным, т.к. не зависит от выбора DirectShow Output вообще. [code] STDMETHODIMP_(double) ISubPicAllocatorPresenterImpl::GetFPS() { return(m_fps); } [/code] При воспроизведении фильмов почти не бывает глюков. Но в этом мире нет ничего идеального. И соответственно, глюки есть. Они проявляются при воспроизведении telecine контента с DVD или его рипов в MPEG2. Проблема в том, что MPEG2 формат не поддерживает нативно частоту кадров 23.967. Только 25.00, 30.00 и 29.97. Для того, чтобы воспроизводить кино 24P на DVD была придумана технология 3:2 Pulldown. Применяя эту технологию,декодер из видеопотока 29.97Гц делает видеоряд в 23.967Гц. Но при этом записывает в PinInfo либо частоту входного видеопотока (MS-декодер, MPC-HC при воспроизведении MPEG2 как файлов) или "0" (MPC-HC при воспроизведении DVD). Выглядит это так: Если проигрывать как DVD. [URL=http://img3.imageshack.us/i/fps5.png/][IMG]http://img3.imageshack.us/img3/7848/fps5.th.png[/IMG][/URL] Если проигрывать как файл. [URL=http://img707.imageshack.us/i/fps6.png/][IMG]http://img707.imageshack.us/img707/8228/fps6.th.png[/IMG][/URL] Декодер в обоих случаях встроенный в MPC-HC. Или можно получить такую статистику: [URL=http://img709.imageshack.us/i/fps7.png/][IMG]http://img709.imageshack.us/img709/3314/fps7.th.png[/IMG][/URL] Как с этим бороться. a. можно дописать MPCVideoDec т.о. чтобы при воспроизведении DVD записывал m_rtTimePerFrame хотя бы исходную частоту кадров видеопотока DVD, как это делают другие декодеры. b. Сколько я не искал, но так и не нашел, где в структурах API воспроизведения DVD указывается декодеру, что нужно использовать 3:2 Pulldown. Ведь как-то декодер узнает об этом. 3. Третий способ. [URL=http://img638.imageshack.us/i/fps4.png/][IMG]http://img638.imageshack.us/img638/8476/fps4.th.png[/IMG][/URL] Это вообще хитрый способ. Окончательное значение FPS получается при вызове функции CDX9AllocatorPresenter::GetFrameRate(). Она короткая и приведу в полном виде. [code] double CDX9AllocatorPresenter::GetFrameRate() { if (m_DetectedLock) return m_DetectedFrameRate; return 10000000.0 / m_rtTimePerFrame; } [/code] Как видно, пока не установлен признак m_DetectedLock значение частоты вычисляется вторым способом, иначе FPS=m_DetectedFrameRate m_DetectedLock и m_DetectedFrameRate вычисляются в функции CEVRAllocatorPresenter::MoveToScheduledList(...). m_DetectedFrameRate - пределяется довольно сложним статистическими методами. Пока m_DetectedFrameRate не определена m_DetectedLock равно false. При выводе информации по Ctrl+J зафиксированная статистическим методом величина помечается буквой "L" после значения, если буквы нет, то выводится FPS рассчитанная описанным выше вторым способом. В алгоритме применен метод фиксирования частоты, который не дает ей скакать. Я не видел ни разу, чтобы вычисления FPS таким способом были ошибочными. Но и у этого метода есть минусы. a. Т.к. он использует статистический анализ, то существует задержка, пока наберутся данные. Задержка может составлять от 2 до 10 секунд. b. Он не является универсальным, т.к. работает ТОЛЬКО при использовании EVR-Custom. 4. Четвертый способ. Еще один способ измерения частоты используется ar-jar в его EVR Sync. Но он опять же не универсальный, так как работает только в EVR Sync и значение частоты там дергается. Т.е. показывается текущее мгновенное значение. Поэтому я даже не стал детально разбираться. Как определяются частоты для автосмены режима монитора. При проигрывании файлов используется второй способ. Т.к. не зависит от DirectShow Output и не дает задержек. Естественно он не работает с Reclock, т.к. Reclock меняет частоту вывода на монитор, а значение m_rtTimePerFrame в VIDEOINFOHEADER Structure нет. Использование статистических методов определения FPS либо увеличит количество ошибочных переключений, либо существенно ограничит использование DirectShow Output. Есть еще вариант вынести алгоритм из третьего способа в отдельную процедуру в модуле MainFrm, но это не избавит от задержек. Кроме того мне не хватает опыта для организации семплировния в этом модуле. Я даже не знаю, возможно ли это. Т.ч. лучший способ совместного использования автосмены режима монитора и Reclock - это написать автосмену в Reclock. Он является активной задающей частоту вывода картинки программой и всегда знает FPS. При проигрывании DVD используется 5-й способ. Основанный на API проигрывания DVD. Способ, по идее, не зависит ни от декодеров, ни от сплиттеров. Частота кадров в DVD помечается в признаке DVD_TIMECODE_FLAGS структуры DVD_PLAYBACK_LOCATION2. Он может иметь след. значения. typedef enum tagDVD_TIMECODE_FLAGS { DVD_TC_FLAG_25fps = 0x00000001, DVD_TC_FLAG_30fps = 0x00000002, DVD_TC_FLAG_DropFrame = 0x00000004, DVD_TC_FLAG_Interpolated = 0x00000008 } DVD_TIMECODE_FLAGS; DVD_TC_FLAG_25fps - Disc is authored to play at 25 frames per second. DVD_TC_FLAG_30fps - Disc is authored to play at 30 frames per second. DVD_TC_FLAG_DropFrame - Disc is authored to play at 29.97 frames per second. Остается еще DVD_TC_FLAG_Interpolated, но он по тому, как написана программа программы дает в итоге FPS=25. Я сделал так же. Т.ч. присутствует проблема с 3:2 Pulldown. Если кто подскажет, как решить, буду премного благодарен. Общий итого: 1. В экране настойки автосмены режима монитора честно напишу честное предупреждение, что это не работает с Reclock. Считаю, что примененные методы являются оптимальными, если кто сомневается, то пусть попробует сделать сам. 2. Так же честно напишу, что есть проблемы при воспроизведении DVD с 3:2 Pulldown. ------------------------------- Ссылку на этот пост размещу на Doom9 с просьбой перевести на английский. У самого не хватает времени, да и мой английский не так хорош.