Титр собственного изготовления
Модераторы: ElenVR, Людмила, PR
-
- Сообщения: 90
- Зарегистрирован: 04 сен 2008 01:50
- Откуда: Красноярск
Титр собственного изготовления
Здравствуйте!
Есть задача: выводить на FD300 собственную динамическую графику.
В смысле, есть приложение, которое умеет рисовать 32х битные "битмапы" на Matrox CG2000. Нужно, чтобы то же самое начало рисоваться на FD300.
И эта графика должна включаться/выключаться по командам из расписания OnAir.
Подскажите, как можно данную задачу реализовать?
Напрашивается вариант разработки собственного титровального объекта для FDTitleDesigner на подобии часов или логотипа, но в SDK такой фишки не нашел.
Может, плохо искал?
Есть задача: выводить на FD300 собственную динамическую графику.
В смысле, есть приложение, которое умеет рисовать 32х битные "битмапы" на Matrox CG2000. Нужно, чтобы то же самое начало рисоваться на FD300.
И эта графика должна включаться/выключаться по командам из расписания OnAir.
Подскажите, как можно данную задачу реализовать?
Напрашивается вариант разработки собственного титровального объекта для FDTitleDesigner на подобии часов или логотипа, но в SDK такой фишки не нашел.
Может, плохо искал?
-
- Сообщения: 7093
- Зарегистрирован: 26 фев 2004 09:53
- Откуда: Techsupport SoftLab-NSK
1)SDK по созданию собственного титровального элемента, который бы виделся в FDTitleDesigner у нас нет. Может быть в дальнейшем появится, но сроки сказать пока невозможно.
2)Вашу задачу можно решить через низкоуровневое титровальное SDK. Оно позволяет показывать последовательность изображений, которые могут генерироваться внешним приложением. Отрисовка в этом случае производится в FIFO (кольцевой буфер) из которого происходит показ на экран с помощью платы FD300. Соответствующий раздел SDK называется SLTitleSDK.
3)Управление показом можно делать с помощью, например, SLMessageServer путем отправки сообщений внешнему приложению. Опыт, насколько мы помним по общению в форуме, в этом вопросе у вас есть.
Есть еще вариант - наш старый интерфейс, который позволяет посылать из расписания программы OnAir оконные команды Windows во внешние приложения. Он описан в нашем SDK в разделе Other. Документ называется OnAirExternalTaskMsg.doc
2)Вашу задачу можно решить через низкоуровневое титровальное SDK. Оно позволяет показывать последовательность изображений, которые могут генерироваться внешним приложением. Отрисовка в этом случае производится в FIFO (кольцевой буфер) из которого происходит показ на экран с помощью платы FD300. Соответствующий раздел SDK называется SLTitleSDK.
3)Управление показом можно делать с помощью, например, SLMessageServer путем отправки сообщений внешнему приложению. Опыт, насколько мы помним по общению в форуме, в этом вопросе у вас есть.
Есть еще вариант - наш старый интерфейс, который позволяет посылать из расписания программы OnAir оконные команды Windows во внешние приложения. Он описан в нашем SDK в разделе Other. Документ называется OnAirExternalTaskMsg.doc
-
- Сообщения: 90
- Зарегистрирован: 04 сен 2008 01:50
- Откуда: Красноярск
Спасибо, я так и думал, но была слабая надеждаДаниленко Сергей писал(а): 2)Вашу задачу можно решить через низкоуровневое титровальное SDK. Оно позволяет показывать последовательность изображений, которые могут генерироваться внешним приложением. Отрисовка в этом случае производится в FIFO (кольцевой буфер) из которого происходит показ на экран с помощью платы FD300. Соответствующий раздел SDK называется SLTitleSDK.

Еще пару вопросов тогда:
какого размера буфер (в экранах?)?
что будет происходить при пересечении регионов моей программы с регионами OnAir (тировальных объектов)?
-
- Сообщения: 7093
- Зарегистрирован: 26 фев 2004 09:53
- Откуда: Techsupport SoftLab-NSK
Во-первых, есть размер картинки (т.е. не обязательно ваш титр должен быть полноэкранным). Во-вторых, есть глубина FIFO, т.е. сколько таких последовательных картинок вы используете.какого размера буфер (в экранах?)?
Оба параметра задаете вы сами.
В нашей титровальной системе есть понятие Z-кординаты. Каждый титровальный элемент имеет свою Z-координату и не может быть элементов с одной Z-координатой. Другими словами в каждом титровальном слое может находиться только один титровальный элемент. Этим обеспечивается однозначное расположение титров на экране по "глубине" (кто над кем рисуется).что будет происходить при пересечении регионов моей программы с регионами OnAir (тировальных объектов)?
При работе через SDK вы указываете Z-координату для своих титров. Так что при пересечении титров разного типа кто-то кого-то будет перекрывать в зависимости как вы укажите Z-координату.
-
- Сообщения: 90
- Зарегистрирован: 04 сен 2008 01:50
- Откуда: Красноярск
Здравствуйте!
Что-то не очень получается у меня реализовать задуманное. А конкретно, ну удается добиться плавного перемещения бегущей строки. Она, во-первых, движется с некой "дрожью", а во-вторых, периодически двигается с "подрывами". Полагаю, что я неверно понял примеры из SDK. Прошу помочь разобраться в этом.
Есть вот такой вот тестовый код основного цикла отрисовки:
Отрисовка в DrawImage1 - простое копированеи памяти, занимает очень мало времени. Sleep(40) установлено просто из соображений 25 FPS. Однако, если уменьшить это значение, то region->GetShotBuff перестает возвращать корректный буфер (не успевает?), хотя размер FIFO гораздо больше размера одного кадра (4000000 против 185000).
Думаю, что я не уловил какой-то принципиальный момент в механизме отрисовки. Растолкуйте, пожалуйста!
Спасибо.
Что-то не очень получается у меня реализовать задуманное. А конкретно, ну удается добиться плавного перемещения бегущей строки. Она, во-первых, движется с некой "дрожью", а во-вторых, периодически двигается с "подрывами". Полагаю, что я неверно понял примеры из SDK. Прошу помочь разобраться в этом.
Есть вот такой вот тестовый код основного цикла отрисовки:
Код: Выделить всё
while (true) {
THROW_FAILED(region->GetShotBuff(sizeRequired, sizeRequired, &buff, &size, 40),
_T("Не удалось получить FIFO буфер для кадра!"));
DrawImage1(WIDTH, HEIGHT, buff);
// confirm valid image data
CTitleShotInfo shotInfo;
shotInfo.DataType = TitleShotDataType_RGBA;
shotInfo.ShotNumber = frame;
shotInfo.dx = WIDTH;
shotInfo.dy = HEIGHT;
THROW_FAILED(region->ConfirmShotSize(0, sizeRequired, &shotInfo),
_T("Буфер не прошел валидацию!"));
// Activate and run region
THROW_FAILED(region->SetActive(TRUE, TRUE, 0),
_T("Не удалось активировать регион!"));
if (_kbhit() && _getch() == KEY_ESC)
break;
//color += 8;
frame++;
Sleep(40);
}
Код: Выделить всё
const long WIDTH = 720;
const long HEIGHT = 64;
...
// create COM-object for application alive checking
CComPtr<IUnknown> holder;
THROW_FAILED(holder.CoCreateInstance(CLSID_SLResourceHolder),
_T("Не удалось создать экземпляр SLResourceHolder!"));
CComPtr<IUnknown> unk;
CComPtr<ISLTitleRegion> region;
THROW_FAILED(surface->CreateTitleRectRegion(holder, 4000000, 4000000, &unk),
_T("Не удалось создать регион!"));
Спасибо.
-
- Сообщения: 493
- Зарегистрирован: 04 янв 2004 12:45
- Откуда: СофтЛаб-НСК
Есть два замечания по коду:
В вашем коде необходимо копировать разные данные в четные и нечетные строки (в верхнее и нижнее поле).
Ваше приложение заполняет фифо, а титровальное ядро "вытаскивает" из фифо кадры и показывает их на плате с частотой кадров платы FD300. Ваше приложение должно стараться держать фифо максимально заполненным. То есть проверять, что в фифо есть свободное место и если место есть, то генерировать очередной кадр (два поля). А если места нет, то тогда выполнять Sleep(40).
Соответственно, в вашем коде надо поправить проверку заполненности фифо:
В телевидении используется чересстрочная развертка, когда четные и нечетные строки одного кадра (одного изображения в нашем случае) показываются в разное время (сдвинуты друг относительно друга на 20 мс). В нашем SDK у интерфейса ISLTitleTarget есть метод GetTargetParams(), который возвращает размеры экрана, частоту кадров и сдвиг во времени верхнего и нижнего поля (от начала кадра). Если порядок полей UpperFieldFirst, то в поле m_LowerFieldTimerShift будет стоять величина 0,020. Если порядок полей LowerFieldFirst, то в поле m_UpperFieldTimerShift будет стоять величина 0,020.движется с некой "дрожью"
В вашем коде необходимо копировать разные данные в четные и нечетные строки (в верхнее и нижнее поле).
Здесь надо обяснить, как работает титровальное фифо.периодически двигается с "подрывами"
Ваше приложение заполняет фифо, а титровальное ядро "вытаскивает" из фифо кадры и показывает их на плате с частотой кадров платы FD300. Ваше приложение должно стараться держать фифо максимально заполненным. То есть проверять, что в фифо есть свободное место и если место есть, то генерировать очередной кадр (два поля). А если места нет, то тогда выполнять Sleep(40).
Соответственно, в вашем коде надо поправить проверку заполненности фифо:
Код: Выделить всё
HRESULT hres = region->GetShotBuff(sizeRequired, sizeRequired, &buff, &size, 40);
if( hres==S_OK ) {
DrawImage();
... // остальной код, как он и был
} else if( hres==S_FALSE ) {
// нет свободного места в фифо - надо подождать, когда оно появится
Sleep(40);
} else { // какая-то ошибка - ломаемся
THROW_FAILED(...)
}
-
- Сообщения: 493
- Зарегистрирован: 04 янв 2004 12:45
- Откуда: СофтЛаб-НСК
-
- Сообщения: 90
- Зарегистрирован: 04 сен 2008 01:50
- Откуда: Красноярск
То есть фифо фрейм содержит сразу оба полукадра? Мне просто не совсем ясен механизм возникновения дрожи. Даже если я помещаю в один фифо фрейм не сдвинутые поля, то это может лишь замедлить строку в два раза, но не должно вызывать дрожь.Игорь Таранцев писал(а): В вашем коде необходимо копировать разные данные в четные и нечетные строки (в верхнее и нижнее поле).
Один раз в рамках создания/инициализации региона?Игорь Таранцев писал(а): И еще одно мелкое замечание - вызывать SetActive() на каждом кадре не рекомендуется. Лучше вызвать один раз.
-
- Сообщения: 493
- Зарегистрирован: 04 янв 2004 12:45
- Откуда: СофтЛаб-НСК
Да, именно так.То есть фифо фрейм содержит сразу оба полукадра?
Дрожь возникает из-за свойств человеческого зрения. Пусть картинка в каждом кадре смещается на 2 пиксела влево. Тогда при показе первого поля картинка смещается на 2 пиксела влево, а при показе второго поля - остается на месте.Мне просто не совсем ясен механизм возникновения дрожи. Даже если я помещаю в один фифо фрейм не сдвинутые поля, то это может лишь замедлить строку в два раза, но не должно вызывать дрожь.
Рассмотрим поведение глаза. Глаз старается отслеживать положение картинки в пространстве. Когда в одном поле картинка сместилась на 2 пиксела влево, то глаз ожидает увидеть ее в следующем поле еще на 2 пиксела влево. В следующем поле он ее на находит в ожидаемом месте, но находит чуть сзади и решает, что картинка поехала назад. В следующем поле глаз опять не находит картинку в ожидаеом месте (сзади), а видит, что картинка в очередной раз дернулась, но уже вперед. И так далее. Глаз видит всякий раз картинку в "новом" месте, а не там, где она должна быть при непрерывном равномерном движении.
Про вызов SetActive().
Досаточно вызывать SetActive() один раз при смене состояния региона - один раз после создания региона при старте показа и один раз при переходе в состояние остановки. Если регион много раз меняет состояние - показывается/останавливается, то и метод SetActive() нужно вызывать много раз.
-
- Сообщения: 90
- Зарегистрирован: 04 сен 2008 01:50
- Откуда: Красноярск
-
- Сообщения: 493
- Зарегистрирован: 04 янв 2004 12:45
- Откуда: СофтЛаб-НСК
-
- Сообщения: 90
- Зарегистрирован: 04 сен 2008 01:50
- Откуда: Красноярск
Не могли бы вы уточнить? То есть лучше забить весь ФИФО кадрами и только потом вызывать SetActive, а дальше уже по мере освобождения блоков (в фифо) добавлять кадры? Если так, то как мне узнать, что фифо забит под завязку? Вероятно, можно вызывать GetShotBuff несколько раз подряд без соотв. вызовов ConfirmShotSize, до тех пор, пока GetShotBuff не вернет S_FALSE, а уже потом для всех полученных буферов вызвать ConfirmShotSize, так?Игорь Таранцев писал(а): Особенно, если сначала заполнить фифо "до конца", а только затем стартовать (активировать) регион.
Или я неверно понял мысль?
-
- Сообщения: 493
- Зарегистрирован: 04 янв 2004 12:45
- Откуда: СофтЛаб-НСК
-
- Сообщения: 493
- Зарегистрирован: 04 янв 2004 12:45
- Откуда: СофтЛаб-НСК
А во время воспроизведения можно узнать заполненность фифо, сравнивая текущее время в фифо (номер кадра, который сейчас показывается) и номер последнего добавленного кадра.
Текущее время возвращает метод GetParameters (интерфейс ISLTitleRegion) - параметр CurrShot струткуры CRegionInfo.
Ну а последений номер Вы знаете сами - то, что Вы указали первым параметром при вызове метода ConfirmShotSize. Кстати, надеюсь Вы увеличиваете этот параметр от кадра к кадру? Очень важно, чтобы для каждого кадра указывался его настоящий номер - именно в это время титровальное ядро пытается показать этот кадр. Если у всех кадров стоит один и тот же номер (например, номер 0), то титровальное ядро будет пропускать все кадры, кроме самого последнего, только-что добавленного в фифо. Поскольку операционная система работает не строго равномерно, то в итоге некоторые кадры будут пропускаться и анимация будет показываться с подрывами.
Текущее время возвращает метод GetParameters (интерфейс ISLTitleRegion) - параметр CurrShot струткуры CRegionInfo.
Ну а последений номер Вы знаете сами - то, что Вы указали первым параметром при вызове метода ConfirmShotSize. Кстати, надеюсь Вы увеличиваете этот параметр от кадра к кадру? Очень важно, чтобы для каждого кадра указывался его настоящий номер - именно в это время титровальное ядро пытается показать этот кадр. Если у всех кадров стоит один и тот же номер (например, номер 0), то титровальное ядро будет пропускать все кадры, кроме самого последнего, только-что добавленного в фифо. Поскольку операционная система работает не строго равномерно, то в итоге некоторые кадры будут пропускаться и анимация будет показываться с подрывами.
-
- Сообщения: 90
- Зарегистрирован: 04 сен 2008 01:50
- Откуда: Красноярск
Подниму старую тему, пожалуй...
Здравствуйте!
Такая ситуация: запускаю свой софт, который работает с титровалкой через SDK, а картинки на экране нету. Хотя на соседнем сервере есть.
Судя по логам моего софта, не производится вычитывание FIFO буфера. Как только мой софт его заполняет под завязку, GetShotBuff начинает возвращать S_FALSE бесконечно долго.
Насколько я помню, раньше такого не наблюдалось. Правда, тесты проводились на другом сервере с другой версией Forward.
Отсюда два вопроса:
1. Зависит ли функциональность, предоставляемая SDK, от версии Forward? Не работает нормально на версии 5.0.2, хотя вся инициализация проходит успешно. На версии 5.2.0 все работает и картинка есть.
2. Мы опять какую-нибудь "птичку" забыли установить в конфиге?
Спасибо.
Здравствуйте!
Такая ситуация: запускаю свой софт, который работает с титровалкой через SDK, а картинки на экране нету. Хотя на соседнем сервере есть.

Судя по логам моего софта, не производится вычитывание FIFO буфера. Как только мой софт его заполняет под завязку, GetShotBuff начинает возвращать S_FALSE бесконечно долго.
Насколько я помню, раньше такого не наблюдалось. Правда, тесты проводились на другом сервере с другой версией Forward.
Отсюда два вопроса:
1. Зависит ли функциональность, предоставляемая SDK, от версии Forward? Не работает нормально на версии 5.0.2, хотя вся инициализация проходит успешно. На версии 5.2.0 все работает и картинка есть.
2. Мы опять какую-нибудь "птичку" забыли установить в конфиге?
Спасибо.