вторую неделю не могу понять в чём дело, может подскажете:
есть граф состоящий из CaptureFilter и рендерера.
CaptureFilter принимает с IP камеры видео поток в H264 и каждому семплу назначает время (через SetTime() и SetMediaTime()). Для SetTime берется stream time фильтра: m_pFilter->StreamTime(rtStart); Для SetMedaTime() берется FILETIME через GetSystemTimeAsFileTime().
Время на камере синхронизируется со временем на сервере.
Всё работает нормально первые несколько часов. Потом визуально изображение начинает отставать от реальности и имеется некий "эффект робота" — часть семплов проигрывается сразу (или отбрасывается). Как я понимаю из MSDN, такое может быть если время семпла "в будущем". Тогда рендерер ждёт этого "будущего" для правильного отображения и/или отображает ключевые фреймы быстрее.
По логам видно, что с камеры приходит равномерный и "правильный" поток (т.е. ключевые фреймы на месте, размеры в норме, равномерно распределены). Но время в графе идет быстрее, чем в системе. Мне не совсем понятно, какое время использует рендерер для отображения? Графа? тогда не должно было быть проблем. Системы? Но там вроде с точностью нелады.
Вот пример времён при старте стрима:
12:06:11( 8852) T5 : VID tStart(0:00:01.970), tStop(0:00:02.036), Bytes(9168) Key(0)
Через сутки видно что tStart (оно же время стрима) ушло вперед на 0.822c.
12:06:08(86406941) T5 : VID tStart(24:00:00.062), tStop(24:00:00.128), Bytes(180) Key(0)
Ещё через сутки ушло на 1.113c
11:06:09(172807739) T5 : VID tStart(48:00:00.860), tStop(48:00:00.926), Bytes(173) Key(0)
(я по логам миллисекунды для времени системы взял, так что довольно точно уход подсчитал)
Что можно сделать? рестартовать граф регулярно? создать свой источник времени (CBaseRefClock) и подтягивать его ко времени системы?
Поблемма скорее всего в следующем: большинство драйверов для плат захвата выставляют времена семплов кое-как. В вашем случае карта захвата скорее всего всетаки дропает некоторые семплы времени от времени, а проставляет время тем которые уже попали в выходную очередь. Соответственно имеем реалный дроп, а по времени всё ок. Выход, только строгий таймкод, привязанный к саждому видео сэмплу.
Здравствуйте, AcidTheProgrammer, Вы писали:
ATP>Поблемма скорее всего в следующем: большинство драйверов для плат захвата выставляют времена семплов кое-как. В вашем случае карта захвата скорее всего всетаки дропает некоторые семплы времени от времени, а проставляет время тем которые уже попали в выходную очередь. Соответственно имеем реалный дроп, а по времени всё ок. Выход, только строгий таймкод, привязанный к саждому видео сэмплу.
Да нет же, источник — IP камера. выдаёт она по RTP свои семплы, которые уже мы проштамповываем временем графа.
дропов с камеры — нет. я по логу вижу, что она регулярно по 15 фреймов в секунду предоставляет. Проблемы появляются _только_ с течением времени и после определенного порога проявляются постоянно — т.е. каждую 1-2 секунды на экране дергается изображение (часть фреймов скипается) и сама картинка отстаёт от реальности на 1-2 секунды.
У нас было такое же для MJPEG — но там все фреймы ключевые и рендерер тупо ждал будущего, в результате фреймрейт падал до одного семпла в неск.секунд. Вылечили грязным хаком — обнуляли timestamp семпла. Попробовать тут тоже обнулять — но боюсь декодеру поплохеет или у нас внутри кто нибудь время спросит...
Может ли быть проблема в том что rtFinish для некоторых фреймов больше, чем rtStart для следующего (на 1-2 mS)?
"строгий таймкод" — это как? SetTime с текущим временем графа — достаточно строго ведь? или надо какое-то другое время надо ставить? timeGetTime()?
VMR7 откуда берет время? системы? или графа? в мсдне как-то туманно всё описано...
Re[3]: DirectShow проблемы со временем в графе?
От:
Аноним
Дата:
01.11.11 05:45
Оценка:
Привет,
В DirectShow есть понятие Preview Pin (http://msdn.microsoft.com/en-us/library/windows/desktop/dd375472(v=vs.85).aspx). Так вот для лайв сорсов (стриминг из инета на екран) без реализации правильного QoS нужно использовать именно его. Preview Pin не выставляет времени на семплах а пушит их столько сколько может, при этом сам дропает семплы которые он считает не нужны (то есть сам реализует QoS). Одно но, Preview Pin не применим для записи в файл. То есть вам необходимо иметь на вашем сорсе как минимум 2 пина.
Помнится я сталкивался с похожей проблемой на предыдущей работе, но доделать времени так и не случилось.
Здравствуйте, NickViz, Вы писали:
NV>Да нет же, источник — IP камера. выдаёт она по RTP свои семплы, которые уже мы проштамповываем временем графа. NV>дропов с камеры — нет. я по логу вижу, что она регулярно по 15 фреймов в секунду предоставляет.
Эты вы так думаете, на самом деле может быть как 14.999... или 15.000...
Не ну это просто было предположение. Ок, попробую попонятней объяснить идею.
Есть камера, есть реальное время (например T). Есть её DSP у которого время течет совершенно иначе (например T1). Кстати камера метки штампует скорее всего по этому времени. Также есть время на приемной, типа SNTP (T2), которое вы считаете эталонным.
На практике эти три времени никогда не совпадают. Естественно у вас будет набегать ошибка и будет в конце концов либо дроп, либо появится дырка.
NV>Проблемы появляются _только_ с течением времени и после определенного порога проявляются постоянно — т.е. каждую 1-2 секунды на экране дергается изображение (часть фреймов скипается) и сама картинка отстаёт от реальности на 1-2 секунды.
Может быть вы недостаточно точно описали эксперимент. То о чем я говорю проявляется примерно после недели нормальной работы, т.е. зависит от точности таймеров оборудования. У вас звук есть? Вы в графе проверяли? У вас фильтр источник свой-самописанный? Вы ставите в графе синхронизацию по времени аудио карты? Часики в графе на аудиокарте горят?
NV>У нас было такое же для MJPEG — но там все фреймы ключевые и рендерер тупо ждал будущего, в результате фреймрейт падал до одного семпла в неск.секунд. Вылечили грязным хаком — обнуляли timestamp семпла. Попробовать тут тоже обнулять — но боюсь декодеру поплохеет или у нас внутри кто нибудь время спросит...
Это все от лукавого.....
NV>Может ли быть проблема в том что rtFinish для некоторых фреймов больше, чем rtStart для следующего (на 1-2 mS)?
Может, но скорее всего проблемма не в этом.
NV>"строгий таймкод" — это как? SetTime с текущим временем графа — достаточно строго ведь? или надо какое-то другое время надо ставить? timeGetTime()? NV>VMR7 откуда берет время? системы? или графа? в мсдне как-то туманно всё описано...
Сначала давайте поймем где у вас рассинхронизация.
Здравствуйте, AcidTheProgrammer, Вы писали:
ATP>Не ну это просто было предположение. Ок, попробую попонятней объяснить идею.
ATP>Есть камера, есть реальное время (например T). Есть её DSP у которого время течет совершенно иначе (например T1). Кстати камера метки штампует скорее всего по этому времени. Также есть время на приемной, типа SNTP (T2), которое вы считаете эталонным. ATP>На практике эти три времени никогда не совпадают. Естественно у вас будет набегать ошибка и будет в конце концов либо дроп, либо появится дырка.
Кмк отношение точности часов на камере и компе не имеет отношения к проблеме. как и точно 15.000 FPS.
В граф приходит сырой фрейм. Для рендерера абсолютно не важно — какое у него было время в камере. И какой FPS задан. Важно — какое у него время в графе, т.е. когда его и на сколько отображать.
Время фрейму проставляется из текущего времени графа. Время стопа — время старта + 1/FPS. Т.е. по идее — как бы время графа не бежало по отношению к камере или системному времени — рендерер должен нормально это дело отображать, т.к. для него фрейм свежий. И вот не выходит каменный цветок. Я вот думаю — может декодер (Axis H264) меняет таймстампы фреймов...
NV>>Проблемы появляются _только_ с течением времени и после определенного порога проявляются постоянно — т.е. каждую 1-2 секунды на экране дергается изображение (часть фреймов скипается) и сама картинка отстаёт от реальности на 1-2 секунды.
ATP>Может быть вы недостаточно точно описали эксперимент. То о чем я говорю проявляется примерно после недели нормальной работы, т.е. зависит от точности таймеров оборудования. У вас звук есть? Вы в графе проверяли? У вас фильтр источник свой-самописанный? Вы ставите в графе синхронизацию по времени аудио карты? Часики в графе на аудиокарте горят?
Далее, немного по "эксперименту": мы сами источник времени в граф не ставим, звука нет.
Граф предельно прост: капчур-фильтр, декодер, рендерер. Всё это внутри нашей системы — надо попробовать в graph editor запустить. Проблема ещё в том, что для проявления рассинхронизации надо ждать 10-12 часов, т.е. полезные идеи проверить можно только на следующий день.
Может стопать и стартовать граф регулярно — по идее время должно обнулиться. раза 3 в сутки...
Николай.
Re[5]: DirectShow проблемы со временем в графе?
От:
Аноним
Дата:
01.11.11 13:04
Оценка:
Здравствуйте, NickViz, Вы писали:
А>>Помнится я сталкивался с похожей проблемой на предыдущей работе, но доделать времени так и не случилось.
NV>Богдан, ну вот ты бы доделал и потом уходил
NV>А на счёт превью пина — так писать то тоже надо... NV>И кстати проблема идёт везде — в записи без AD, в local app и в IE.
NV>Николай В.
О привет.
Необходимо завести два пина. Один нормальный (Capture Pin — уже есть), а второй Preview Pin. Насколько я помню с превью пином можно соединится только насильно или если он только один. То есть DirectShow по дефолту не хочет использовать Preview Pin. То есть добавив его надо будет добавить в плеер код который заставит коннектится именно к Preview Pin. Кода по идее будет не много (идентичный обычному пину только таймстемпы убрать).
NV>Кмк отношение точности часов на камере и компе не имеет отношения к проблеме. как и точно 15.000 FPS. NV>В граф приходит сырой фрейм. Для рендерера абсолютно не важно — какое у него было время в камере. И какой FPS задан. Важно — какое у него время в графе, т.е. когда его и на сколько отображать. NV>Время фрейму проставляется из текущего времени графа. Время стопа — время старта + 1/FPS. Т.е. по идее — как бы время графа не бежало по отношению к камере или системному времени — рендерер должен нормально это дело отображать, т.к. для него фрейм свежий. И вот не выходит каменный цветок. Я вот думаю — может декодер (Axis H264) меняет таймстампы фреймов...
Как это не важно какое время... А время графа у вас откуда берется?? Это что какое-то магическое время которое автоматически подстраивается к любой частоте любого сигнала. Вы с часами графа что-нибудь делаете, если нет то оно как-раз будет системным. По часам графа у вас прошла секунда, а кадров пришло больше, т.к камера награбила больше кадров, у нее свое время. Что рендереру делать с лишними кадрами, естественно дропать и наоборот тормозить проигрывание и ждать пока с камеры что-нибудь придет.
Смотрите — количесто полученных кадров с камеры умноженное на FPS (время потока с камеры) все больше отличается от времени в графе. Ошибка накапливатся — время все больше расходится. До определенного момента рендерер этого не замечает, после определенного момента вы рассинхронизуетесь с рендерером так, что любой кадр рендерится либо тутже (время графа опережает), либо вы начинаете ждать все больше и больше и чем дольше вы играете, тем синее рассинхрон временных шкал. У вас поток начинает проигрываться не плавно, а в соответствии с неравномерными характеристиками канала передачи (сети) либо все буфера забиваются и видео играет пачками, а перерывы между ними все больше и больше.
NV>>>Проблемы появляются _только_ с течением времени и после определенного порога проявляются постоянно — т.е. каждую 1-2 секунды на экране дергается изображение (часть фреймов скипается) и сама картинка отстаёт от реальности на 1-2 секунды.
Так и будет. Рассинхрон будет все сильнее и сильнее.
NV>Далее, немного по "эксперименту": мы сами источник времени в граф не ставим, звука нет.
NV>Граф предельно прост: капчур-фильтр, декодер, рендерер. Всё это внутри нашей системы — надо попробовать в graph editor запустить. Проблема ещё в том, что для проявления рассинхронизации надо ждать 10-12 часов, т.е. полезные идеи проверить можно только на следующий день.
Не хотите забивать голову. Вот решение — уберите вообще время из сэмплов, все тутже будет ОК. С какой скоростью придет с такой и будет играться.
Хотите плавно — придется о времени подумать.
NV>Может стопать и стартовать граф регулярно — по идее время должно обнулиться. раза 3 в сутки...
Можете, завтра у пользователя будет другая камера с другими характеристиками...
NV>Николай.
Юрий.
Здравствуйте, AcidTheProgrammer, Вы писали:
ATP>Как это не важно какое время... А время графа у вас откуда берется?? Это что какое-то магическое время которое автоматически подстраивается к любой частоте любого сигнала. Вы с часами графа что-нибудь делаете, если нет то оно как-раз будет системным. По часам графа у вас прошла секунда, а кадров пришло больше, т.к камера награбила больше кадров, у нее свое время. Что рендереру делать с лишними кадрами, естественно дропать и наоборот тормозить проигрывание и ждать пока с камеры что-нибудь придет.
Что-то я вот подумал, что есть в этом сермяжная правда. Axis драйвер кладёт фреймы в буфер. а капчур фильтр оттуда их забирает... и если медленно забирает — то драйвер по идее выбрасывает часть фреймов (надо бы ещё посмотреть может можно обратно камере намекнуть поумерить пыл).
Это может объяснить проблемы во всех графах что мы бодяжим. Тогда получается надо задавать драйверу немного меньший фрейм рейт, чем графу. Ну или графу быстрее чем драйверу.
Кстати вопрос: у нас на капчур фильтре реализован QoS (через IQualityControl::Notify(IBaseFilter *pSelf, Quality q)). так вот — ни одного сообщения QoS я не видел. Значит ли это, что рендерер не посылал их, или это промежуточный фильтр не поддерживает QoS?
Т.е. достаточно ли на первом фильтре поддерживать (override) Notify() что бы рендерер мог отправлять фидбеки — или надо что бы _все_ фильтры между первым и рендерером поддеживали это? или мало имплементировать, надо ещё и Sink сделать?
Хм — CBaseVideoRenderer тоже переопределяет Notify — но кто его вызывает тогда? он же?
ATP>Смотрите — количесто полученных кадров с камеры умноженное на FPS (время потока с камеры) все больше отличается от
Похоже не в рендерере дело. Буду смотреть буфер в самом драйвере камеры..
ATP>Не хотите забивать голову. Вот решение — уберите вообще время из сэмплов, все тутже будет ОК. С какой скоростью придет с такой и будет играться.
Кстати — нет. не проканало. ещё одно подтверждение, что дело не в графе вообще. стрим ему приходит кривоватый (торопится).
NV>>Может стопать и стартовать граф регулярно — по идее время должно обнулиться. раза 3 в сутки... ATP>Можете, завтра у пользователя будет другая камера с другими характеристиками...
А мы этот параметр в реестр предусмотрительно вынесем
Здравствуйте, NickViz, Вы писали:
NV>Кстати вопрос: у нас на капчур фильтре реализован QoS (через IQualityControl::Notify(IBaseFilter *pSelf, Quality q)). так вот — ни одного сообщения QoS я не видел. Значит ли это, что рендерер не посылал их, или это промежуточный фильтр не поддерживает QoS? NV>Т.е. достаточно ли на первом фильтре поддерживать (override) Notify() что бы рендерер мог отправлять фидбеки — или надо что бы _все_ фильтры между первым и рендерером поддеживали это? или мало имплементировать, надо ещё и Sink сделать?
Должны поддержвать все, по цепочке. Но обычно декодер забирает все нотификации себе, т.к. ему типа виднее в uncompressed формате.
NV>Хм — CBaseVideoRenderer тоже переопределяет Notify — но кто его вызывает тогда? он же?
Забейте вы на Notify — пусть декодер этим занимается.
NV>Похоже не в рендерере дело. Буду смотреть буфер в самом драйвере камеры..
Поймите простую вещь, что весь это механизм работает тольно с файлами, (точнее с потоками не в реальном времени), которые, грубо говоря, могут менять скорость подачи от 0 до +безконечности. С потоками реального времени, все намного сложнее, придется учитывать расхождение временных шкал.
NV>Кстати — нет. не проканало. ещё одно подтверждение, что дело не в графе вообще. стрим ему приходит кривоватый (торопится).
Вот это уже очень странно, такого быть не может. Видимо ваш деодер сам метки времени проставляет. В каком месте вы обнуляете метки? Важно поставить метки у некомпрессированных семплов. Нет меток — означает играть со скоростью приема. Кто тогда у вас в графе держит поток? Вы чего-то не договариваете
NV>>>Может стопать и стартовать граф регулярно — по идее время должно обнулиться. раза 3 в сутки... ATP>>Можете, завтра у пользователя будет другая камера с другими характеристиками... NV>А мы этот параметр в реестр предусмотрительно вынесем
Конечно все можно, но очевидно что у вас в потоке воспроизведения какая-то неучтенная проблемма, которая вам потом сильно аукнеться, поверте
победили в итоге. Как оказалось, Axis камера в темноте снижала фрейм рейт с 15 до 5FPS. А с приходом света — повышала обратно, но не до 15 а до 30. Как результат мы не выгребали все фреймы. Баг в фирмваре, Axis поправил.
Здравствуйте, NickViz, Вы писали:
NV>Здравствуйте, AcidTheProgrammer:
NV>победили в итоге. Как оказалось, Axis камера в темноте снижала фрейм рейт с 15 до 5FPS. А с приходом света — повышала обратно, но не до 15 а до 30. Как результат мы не выгребали все фреймы. Баг в фирмваре, Axis поправил.
NV>Николай.
Поздравляю! На моей памяти нет ни одного производителя плат захвата который бы хоть как-то не накосячил в реализации, или не добавил бы свои особенности. Больше всего раздражает когда глюки происходят, казалось бы, в профессиональном телевизионном оборудовании. Но что поделать — это реалии.