Некоторые полезные примеры и сценарии
Эта глава содержит много примеров, которые могут помочь Вам сплотить весь материал в этой книге путем исследования структуры атома, следующей из многих различных сценариев.
Глава разделена на следующие темы:
Создание, Копирование и Избавление от Контейнеров Atom обсуждает различные способы, можно работать с контейнерами атома, вместе с иллюстрациями и примером кода, показывающими использование.
Preparing Sound and Subtitle Alternate Groups для Использования с Устройствами Apple обсуждает, как многократные дорожки с различными языками могут быть связаны друг с другом.
Создание Описания Эффекта обсуждает, как Вы создаете описание эффекта путем создания контейнера атома, вставки атома QT, указывающего эффект и вставку ряда атомов QT, устанавливающих его параметры.
Создание Фильмов с Дорожками Модификатора обеспечивает пример кода, показывающий Вам, как создать фильм с дорожками модификатора.
Авторская разработка Фильмов с Внешними Целями Фильма обсуждает, как создать фильмы с внешними целями.
Создание Видеотреков в 30 Кадрах в секунду обсуждает видео создания 30 кадр/с.
Создание Видеотреков в 29.97 Кадрах в секунду описывает видео создания 29,97 кадр/с.
Создание Звуковых дорожек в 44,1 кГц обеспечивает пример создания звуковой дорожки.
Создание Дорожки Временного кода для Видео на 29,97 футов в секунду представляет пример дорожки временного кода.
Игра со Списками Редактирования обсуждает, как интерпретировать данные списка редактирования.
Чередование Данных Фильма показывает, как дорожки фильма чередованы в файле данных фильма.
Ссылка на Два Файла данных С Одноколейным путем показывает, как данные дорожки могут находиться больше чем в одном файле.
Получение имени QuickTime, который обсуждает Узел VR, как можно использовать стандартные функции контейнера атома QuickTime для получения информации в QuickTime атом заголовка узла VR.
Добавление Пользовательских Атомов в QuickTime, который описывает Фильм VR, как добавить пользовательские атомы или к QuickTime мир VR или к контейнерам атома информации об узле.
Добавление Контейнеров Atom в QuickTime, который Фильм VR показывает коду, который Вы использовали бы для добавления мира VR и контейнеров атома информации об узле к дорожке QTVR.
Оптимизация QuickTime, который описывают Фильмы VR для веб-Воспроизведения, как использовать Рихтовочный инструмент QTVR, компонент экспорта фильма, преобразовывающий существующий QuickTime VR единственный фильм узла в новый фильм, оптимизированный для просмотра в сети.
Создание, копирование и избавление от контейнеров Atom
Прежде чем можно будет добавить атомы к контейнеру атома, необходимо сначала создать контейнер путем вызова QTNewAtomContainer. Пример кода, показанный в вызовах Перечисления 6-1 QTNewAtomContainer создать контейнер атома.
Перечисление 6-1 , Создающее новый контейнер атома
QTAtomContainer spriteData; |
OSErr err |
// create an atom container to hold a sprite’s data |
err=QTNewAtomContainer (&spriteData); |
Когда Вы закончили использовать контейнер атома, необходимо избавиться от него путем вызова QTDisposeAtomContainer функция. Пример кода, показанный в вызовах Перечисления 6-2 QTDisposeAtomContainer избавляться spriteData контейнер атома.
Перечисление 6-2 , Избавляющееся от контейнера атома
if (spriteData) |
QTDisposeAtomContainer (spriteData); |
Создание новых атомов
Можно использовать QTInsertChild функция, чтобы создать новые атомы и вставить их в контейнер атома QT. QTInsertChild функция создает новый дочерний атом для родительского атома. Вызывающая сторона указывает тип атома и атом ID для нового атома. Если Вы указываете значение 0 для атома ID, QTInsertChild присваивает уникальный идентификатор атому.
QTInsertChild вставляет атом в дочерний список родителя в индексе, указанном index параметр; любые существующие атомы в том же индексе или больше перемещены к концу дочернего списка. Если Вы указываете значение 0 для index параметр, QTInsertChild вставляет атом в конце дочернего списка.
Пример кода в Перечислении 6-3 создает новый контейнер атома QT и вызовы QTInsertChild добавить атом. Получающийся контейнер атома QT показан на рисунке 6-1. Значение смещения 10 возвращается в firstAtom параметр.
Перечисление 6-3 , Создающее новый контейнер атома QT и вызов QTInsertChild добавить атом.
QTAtom firstAtom; |
QTAtomContainer container; |
OSErr err |
err = QTNewAtomContainer (&container); |
if (!err) |
err = QTInsertChild (container, kParentAtomIsContainer, 'abcd', |
1000, 1, 0, nil, &firstAtom); |

Следующие вызовы примера кода QTInsertChild создать второй дочерний атом. Поскольку значение 1 указано для index параметр, второй атом вставляется перед первым атомом в дочернем списке; индекс первого атома изменяется на 2. Получающийся контейнер атома QT показан на рисунке 6-2.
QTAtom secondAtom; |
FailOSErr (QTInsertChild (container, kParentAtomIsContainer, 'abcd', |
2000, 1, 0, nil, &secondAtom)); |

Можно вызвать QTFindChildByID функция для получения измененного смещения первого атома, вставленного, как показано в следующем примере. В этом примере, QTFindChildByID функционируйте возвращает смещение 20.
firstAtom = QTFindChildByID (container, kParentAtomIsContainer, 'abcd', |
1000, nil); |
Перечисление 6-4 показывает как QTInsertChild функция вставляет листовой атом в контейнер атома sprite. Новый листовой атом содержит индекс изображения спрайта как свои данные.
Перечисление 6-4 , Вставляющее дочерний атом
if ((propertyAtom = QTFindChildByIndex (sprite, kParentAtomIsContainer, |
kSpritePropertyImageIndex, 1, nil)) == 0) |
FailOSErr (QTInsertChild (sprite, kParentAtomIsContainer, |
kSpritePropertyImageIndex, 1, 1, sizeof(short),&imageIndex, |
nil)); |
Копирование существующих атомов
QuickTime обеспечивает несколько функций для копирования существующих атомов в контейнере атома. QTInsertChildren функция вставляет контейнер атомов как дочерние элементы родительского атома в другом контейнере атома. Рисунок 6-3 показывает двум примерам контейнеры атома QT, A и B.

Следующие вызовы примера кода QTFindChildByID получать смещение атома в контейнере A. Затем пример кода вызывает QTInsertChildren функционируйте для вставки атомов в контейнер B как дочерние элементы атома в контейнере A. Рисунок 6-4 показывает, какой контейнер взгляды как после атомов от контейнера B были вставлены.
QTAtom targetAtom; |
targetAtom = QTFindChildByID (containerA, kParentAtomIsContainer, 'abcd', |
1000, nil); |
FailOSErr (QTInsertChildren (containerA, targetAtom, containerB)); |

В перечислении 6-5, QTInsertChild функция вставляет родительский атом в контейнер атома theSample. Затем вызовы кода QTInsertChildren вставить контейнер theSprite в контейнер theSample. Родительский атом newSpriteAtom.
Перечисление 6-5 , Вставляющее контейнер в другой контейнер
FailOSErr (QTInsertChild (theSample, kParentAtomIsContainer, |
kSpriteAtomType, spriteID, 0, 0, nil, &newSpriteAtom)); |
FailOSErr (QTInsertChildren (theSample, newSpriteAtom, theSprite)); |
QuickTime обеспечивает три других функции, которые можно использовать для управления атомами в контейнере атома. QTReplaceAtom функционируйте заменяет атом и его дочерние элементы с различным атомом и его дочерние элементы. Можно вызвать QTSwapAtoms функционируйте для свопинга содержания двух атомов в контейнере атома; после свопинга, ID и индекса каждого атома остается тем же. QTCopyAtom функционируйте копирует атом и его дочерние элементы к новому контейнеру атома.
Получение атомов от контейнера Atom
QuickTime обеспечивает функции, которые можно использовать, чтобы получить информацию о типах дочерних элементов родительского атома, искать определенный атом и получить листовые данные атома.
Можно использовать QTCountChildrenOfType и QTGetNextChildType функции для получения информации о типах дочерних элементов атома. QTCountChildrenOfType функционируйте возвращает число дочерних элементов данного типа атома для родительского атома. QTGetNextChildType функционируйте возвращает следующий тип атома в дочернем списке родительского атома.
Можно использовать QTFindChildByIndex, QTFindChildByID, и QTNextChildAnyType функции для получения атома. Вы вызываете QTFindChildByIndex функционируйте, чтобы искать и получить дочерний элемент родительского атома его типом и индексом в том типе.
Перечисление 6-6 показывает функцию примера кода SetSpriteData, который обновляет контейнер атома, описывающий спрайт. (Для получения дополнительной информации о спрайтах и Панели инструментов Sprite, обратитесь к книге Programming With Wired Movies и Sprite Animation, доступной в http://developer.apple.com/techpubs/quicktime/qtdevdocs/RM/PDF.htm.) Для каждого свойства спрайта, который должен быть обновлен, SetSpriteData вызовы QTFindChildByIndex получать надлежащий атом от контейнера атома. Если атом найден, SetSpriteData вызовы QTSetAtomData заменять данные атома новым значением свойства. Если атом не найден, SetSpriteData вызовы QTInsertChild добавить новый атом для свойства.
Перечисление 6-6 , Находящее дочерний атом индексом
OSErr SetSpriteData (QTAtomContainer sprite, Point *location, |
short *visible, short *layer, short *imageIndex) |
{ |
OSErr err = noErr; |
QTAtom propertyAtom; |
// if the sprite’s visible property has a new value |
if (visible) |
{ |
// retrieve the atom for the visible property -- |
// if none exists, insert one |
if ((propertyAtom = QTFindChildByIndex (sprite, |
kParentAtomIsContainer, kSpritePropertyVisible, 1, |
nil)) == 0) |
FailOSErr (QTInsertChild (sprite, kParentAtomIsContainer, |
kSpritePropertyVisible, 1, 1, sizeof(short), visible, |
nil)) |
// if an atom does exist, update its data |
else |
FailOSErr (QTSetAtomData (sprite, propertyAtom, |
sizeof(short), visible)); |
} |
// ... |
// handle other sprite properties |
// ... |
} |
Можно вызвать QTFindChildByID функционируйте, чтобы искать и получить дочерний элемент родительского атома его типом и ID. Функция примера кода AddSpriteToSample, показанный в Перечислении 6-7, добавляет спрайт, представленный контейнером атома, к ключевой выборке, представленной другим контейнером атома. AddSpriteToSample вызовы QTFindChildByID определить ли контейнер атома theSample содержит атом типа kSpriteAtomType с ID spriteID. В противном случае AddSpriteToSample вызовы QTInsertChild вставить атом с тем типом и ID. Значение 0 передается для index параметр, чтобы указать, что атом должен быть вставлен в конце дочернего списка. Значение 0 передается для dataSize параметр, чтобы указать, что атом не имеет никаких данных. Затем AddSpriteToSample вызовы QTInsertChildren вставить атомы в контейнер theSprite как дочерние элементы нового атома. FailIf и FailOSErr макросы, которые выходят из текущей функции, когда происходит ошибка.
Перечисление 6-7 , Находящее дочерний атом ID
OSErr AddSpriteToSample (QTAtomContainer theSample, |
QTAtomContainer theSprite, short spriteID) |
{ |
OSErr err = noErr; |
QTAtom newSpriteAtom; |
FailIf (QTFindChildByID (theSample, kParentAtomIsContainer, |
kSpriteAtomType, spriteID, nil), paramErr); |
FailOSErr (QTInsertChild (theSample, kParentAtomIsContainer, |
kSpriteAtomType, spriteID, 0, 0, nil, &newSpriteAtom)); |
FailOSErr (QTInsertChildren (theSample, newSpriteAtom, theSprite)); |
} |
Как только Вы получили дочерний атом, можно вызвать QTNextChildAnyType функция для получения последующих дочерних элементов родительского атома. QTNextChildAnyType возвращает смещение следующему атому любого типа в дочернем списке родительского атома. Эта функция полезна для итерации через дочерние элементы родительского атома быстро.
QuickTime также обеспечивает функции для получения типа атома, ID и данных. Можно вызвать QTGetAtomTypeAndID функция для получения типа атома и ID. Можно получить доступ к данным атома одним из трех способов.
Для копирования данных атома в дескриптор можно использовать
QTCopyAtomDataToHandleфункция.Для копирования данных атома в указатель можно использовать
QTCopyAtomDataToPtrфункция.Для доступа к данным атома непосредственно необходимо заблокировать контейнер атома в памяти путем вызова
QTLockContainer. Как только контейнер заблокирован, можно вызватьQTGetAtomDataPtrполучать указатель на данные атома. Когда Вы закончили получать доступ к данным атома, необходимо вызватьQTUnlockContainerфункция для разблокирования контейнера в памяти.
Изменение атомов
QuickTime обеспечивает функции, которые можно вызвать для изменения атрибутов или данных, связанных с атомом в контейнере атома. Для изменения ID атома Вы вызываете функцию QTSetAtomID.
Вы используете QTSetAtomData функционируйте для обновления данных, связанных с листовым атомом в контейнере атома. QTSetAtomData функционируйте заменяет листовые данные атома новыми данными. Пример кода в вызовах Перечисления 6-8 QTFindChildByIndex определить, содержит ли контейнер атома видимое свойство спрайта. Если так, демонстрационные вызовы QTSetAtomData заменять данные атома новым видимым свойством.
Перечисление 6-8 , Изменяющее данные атома
QTAtom propertyAtom; |
// if the atom isn’t in the container, add it |
if ((propertyAtom = QTFindChildByIndex (sprite, kParentAtomIsContainer, |
kSpritePropertyVisible, 1, nil)) == 0) |
FailOSErr (QTInsertChild (sprite, kParentAtomIsContainer, |
kSpritePropertyVisible, 1, 0, sizeof(short), visible, nil)) |
// if the atom is in the container, replace its data |
else |
FailOSErr (QTSetAtomData (sprite, propertyAtom, sizeof(short), |
visible)); |
Удаление атомов от контейнера Atom
Для удаления атомов из контейнера атома можно использовать QTRemoveAtom и QTRemoveChildren функции. QTRemoveAtom функция удаляет атом и его дочерние элементы, если таковые имеются, от контейнера. QTRemoveChildren функция удаляет дочерние элементы атома из контейнера, но не удаляет сам атом. Можно также использовать QTRemoveChildren удалить все атомы в контейнере атома. Для этого необходимо передать константу kParentAtomIsContainer для atom параметр.
Пример кода, показанный в Перечислении 6-9, добавляет выборки переопределения к дорожке спрайта для анимации спрайтов в дорожке спрайта. sample и spriteData переменные являются контейнерами атома. spriteData контейнер атома содержит атомы, описывающие единственный спрайт. sample контейнер атома содержит атомы, который описывает выборку переопределения.
Каждая итерация for вызовы цикла QTRemoveChildren удалить все атомы от обоих sample и spriteData контейнеры. Пример кода обновляет индекс изображения, которое будет использоваться для спрайта и расположения спрайта и вызовов SetSpriteData (Перечисление 6-6), добавляющее надлежащие атомы к spriteData контейнер атома. Затем вызовы примера кода AddSpriteToSample (Перечисление 6-7) для добавления spriteData контейнер атома к sample контейнер атома. Наконец, когда все спрайты были обновлены, вызовы примера кода AddSpriteSampleToMedia добавить выборку переопределения к дорожке спрайта.
Перечисление 6-9 , Удаляющее атомы из контейнера
QTAtomContainer sample, spriteData; |
// ... |
// add the sprite key sample |
// ... |
// add override samples to make the sprites spin and move |
for (i = 1; i <= kNumOverrideSamples; i++) |
{ |
QTRemoveChildren (sample, kParentAtomIsContainer); |
QTRemoveChildren (spriteData, kParentAtomIsContainer); |
// ... |
// update the sprite: |
// - update the imageIndex |
// - update the location |
// ... |
// add atoms to spriteData atom container |
SetSpriteData (spriteData, &location, nil, nil, &imageIndex); |
// add the spriteData atom container to sample |
err = AddSpriteToSample (sample, spriteData, 2); |
// ... |
// update other sprites |
// ... |
// add the sample to the media |
err = AddSpriteSampleToMedia (newMedia, sample, |
kSpriteMediaFrameDuration, false); |
} |
Preparing Sound and Subtitle Alternate Groups для использования с устройствами Apple
Альтернативные группы являются наборами дорожек, что все служат той же цели, где любой дорожкой в группе можно заменить другого в фильме. У элементов той же альтернативной группы есть то же значение идентификатора в альтернативном поле группы в 'tkhd' (отследите заголовок), атом; посмотрите Ссылочные Атомы Дорожки для примера альтернативных дорожек для различных языков.
Этот раздел обеспечивает инструкции для использования альтернативных групп в фильмах, которые будут играться на устройствах Apple.
Общие указания.
Для каждой альтернативной группы:
Группа должна содержать дорожки только одного типа; например, только дорожки подзаголовка или только звуковые дорожки.
Все дорожки того же типа должны быть в единственной альтернативной группе.
Одна дорожка в группе должна быть включена; т.е. флаг Track Enabled должен быть установлен (0x0001) в его заголовке дорожки (
'tkhd').Все другие дорожки в группе должны быть отключены.
Альтернативные дорожки подзаголовка
Для альтернативной группы, содержащей многократный подзаголовок ('sbtl') дорожки:
Проигрыватель должен выбрать дорожку подзаголовка, даже когда выключен дисплей подзаголовка.
Если какое-либо из требований утвердило, в целом не содержит, проигрыватели могут действовать, как будто нет никакой альтернативной информации о дорожке подзаголовка.
Как описано в Демонстрационных Данных Подзаголовка, дорожка подзаголовка может содержать любую комбинацию принудительных (должен быть выведен на экран), и невызвал (дополнительно выведенный на экран) выборки подзаголовка, включая возможность дорожки, содержащей только вызванные выборки подзаголовка. Даже если пользователь указывает, прямо или косвенно, что никакие подзаголовки не должны быть выведены на экран, любая доступная надлежащая дорожка подзаголовка должна быть включена так, чтобы любые принудительные подзаголовки в дорожке могли быть выведены на экран. Средние значения, которыми проигрыватель может сделать выбор по умолчанию среди альтернатив подзаголовка в отсутствие пользовательского выбора, покрыты Отношениями Через Alternate Groups.
Для каждого языка в группе альтернативы подзаголовка дорожки подзаголовка могут быть сконфигурированы любым из следующих способов:
Одноколейный путь: Содержит любую комбинацию принудительных и невызванных (регулярных) выборок подзаголовка.
Пары дорожки: Одна дорожка содержит любую комбинацию принудительных и невызванных (регулярных) выборок подзаголовка и имеет ссылку дорожки типа
'forc'это ссылается на вторую дорожку, содержащую только вызванные выборки, как описано в Демонстрационных Данных Подзаголовка.
Если пользователь или проигрыватель выбирают язык пары дорожки, приложение проигрывателя тогда выбирает надлежащую дорожку пары. Это должно выбрать регулярную дорожку подзаголовка, если дисплей подзаголовка работает или принудительная только дорожка подзаголовка, если дисплей подзаголовка выключен.
Если пара дорожки присутствует в группе альтернативы подзаголовка, проигрыватель, выводящий на экран языки дорожки дорожек подзаголовка, может принять решение перечислить язык только один раз. Если проигрыватель перечисляет обе дорожки пары, проигрыватель должен вывести на экран некоторое различие между дорожками (например, включая имена дорожки от 'tnam' пользовательские данные в меню).
Альтернативные звуковые дорожки
Для альтернативной группы, содержащей многократный звук ('soun') дорожки:
Если больше чем одна альтернативная группа содержит звуковые дорожки, альтернативная группа, содержащая включенную звуковую дорожку, должна считаться основной альтернативной группой звуковой дорожки. Должны быть проигнорированы другие альтернативные группы, содержащие звуковые дорожки.
Если существует больше чем одна включенная звуковая дорожка, или если существует включенная звуковая дорожка и незвуковая дорожка в той же альтернативной группе, проигрыватель может действовать, как будто нет никакой альтернативной информации о звуковой дорожке.
Проигрыватели могут проигнорировать звуковые дорожки, использующие кодеки, которые недоступны.
Отношения через Alternate Groups
Аудио альтернативная группа и группа альтернативы подзаголовка, возможно, должны использовать различные языки, потому что первым является разговорный язык, и вторым является письменный язык и BCP могут отличаться, 47 языковых тегов. Если нет потребности дифференцироваться, дорожки и в альтернативных группах должны использовать тот же код языка и в дополнительно расширенный языковой тег.
Звуковые дорожки могут иметь ссылку дорожки типа 'folw' (для «следует») к единственной дорожке подзаголовка; если звуковая дорожка выбрана, эта дорожка является значением по умолчанию, чтобы выбрать. Использование a 'folw' ссылка является нейтрализацией в случаях, где определение языка не может использоваться по некоторым причинам (например, письменный язык и разговорный язык используют различные расширенные языковые теги, как с норвежским языком).
Все дорожки подзаголовка, найденные в группе альтернативы дорожки подзаголовка, являются дорожками кандидата для любой выбранной звуковой дорожки. Никакое средство для ограничения набора доступных дорожек подзаголовка для определенной выбранной звуковой дорожки в настоящее время не определяется. Однако для руководства поведения проигрывателя в делании выбора среди альтернатив подзаголовка в отсутствие пользовательского выбора или предпочтения единственная дорожка подзаголовка может быть связана со звуковой дорожкой следующим образом:
Звуковая дорожка может включать a
'folw'(«следует») за ссылкой дорожки на соответствующую дорожку подзаголовка.Если звуковая дорожка имеет a
'folw'отследите ссылку на дорожку подзаголовка, что дорожка подзаголовка, на которую ссылаются, является дорожкой подзаголовка по умолчанию для той звуковой дорожки.Каждая звуковая дорожка может иметь или нуль или ссылки дорожки 'folw' на дорожку подзаголовка.
Если пара дорожки подзаголовка должна быть сделана значением по умолчанию, звуковая дорожка должна иметь a
'folw'отследите ссылку на принудительную дорожку подзаголовка пары дорожки.Если существует нет
'folw'отследите ссылку на дорожку подзаголовка, проигрыватель обычно определяет дорожку подзаголовка по умолчанию путем соответствия аспектов аудио и дорожек подзаголовка, обычно путем соответствия расширенного языкового тега (или код языка, если нет никакого языкового тега) в наборе дорожек кандидата.Если никакое соответствие не найдено языком, проигрыватель мог бы выбрать другую дорожку кандидата, основанную на пользовательской настройке (например, из списка предпочтительных языков). Другой проигрыватель мог бы выбрать первую дорожку в 'trak' порядке поля в 'moov' среди дорожек кандидата. Другой проигрыватель мог бы иметь другой механизм для выбора значения по умолчанию. Возможные подходы нейтрализации ни не перечисляются, ни ограничиваются здесь. Обратите внимание на то, что выбор никакой дорожки подзаголовка может быть надлежащим.
Если значение по умолчанию, соответствующее между аудио определением языка и определением языка дорожки подзаголовка, не может использоваться, ссылка дорожки 'folw' должна быть создана в медиа-файле. (Например, норвежский язык как разговорное использование различный языковой тег, чем эти два языковых тега для норвежского языка, как записано.)
Создание описания эффекта
Описание эффекта говорит QuickTime, какой эффект выполниться и содержит параметры, управляющие, как эффект ведет себя во время выполнения. Вы создаете описание эффекта путем создания контейнера атома, вставки атома QT, указывающего эффект и вставку ряда атомов QT, устанавливающих его параметры.
Существуют функции поддержки, которые можно вызвать для помощи Вам в этом процессе. QTCreateStandardParameterDialog возвращает полное описание эффекта, которое можно использовать, включая выбранные пользователями настройки; только необходимо добавить kEffectSourceName атомы к описанию для эффектов, требующих источников. На более низком уровне, QTGetEffectsList возвращает список доступных эффектов и ImageCodecGetParameterList возвратит описание параметров для эффекта, включая значение по умолчанию для каждого параметра в форме атома QT, который может быть вставлен непосредственно в описание эффекта.
Структура описания эффекта
Описание эффекта является единственной выборкой носителей для дорожки эффекта. Описание эффекта реализовано как a QTAtomContainer структура, общая структура QuickTime для содержания ряда атомов QuickTime. Все описания эффекта должны содержать набор требуемых атомов, указывающих атрибуты такой как который компонент эффекта использовать. Кроме того, описания эффекта могут содержать переменное число атомов параметра, содержащих значения параметров для эффекта.
Каждый атом содержит или данные или ряд дочерних атомов. Если атом параметра содержит данные, данные являются значением параметра, и это значение остается постоянным, в то время как выполняется эффект. Если атом параметра содержит ряд дочерних атомов, они обычно содержат запись промежуточного кадра, таким образом, значение параметра будет интерполировано на время эффекта.
Вы собираете описание эффекта путем добавления надлежащего набора атомов к a QTAtomContainer структура.
Можно узнать то, что надлежащие атомы путем создания ImageCodecGetParameterList вызовите к компоненту эффекта. Это заполняет контейнер атома рядом атомов описания параметра. Эти атомы содержат описания параметров эффекта, таких как тип атома каждого параметра, диапазон данных, значение по умолчанию, и т.д. Значение по умолчанию в каждом атоме описания самостоятельно a QTAtom это может быть вставлено непосредственно в Ваше описание эффекта.
Можно изменить данные в атомах параметра непосредственно или позволить пользователю установить их путем вызова QTCreateStandardParameterDialog, который возвращает полное описание эффекта (необходимо добавить kEffectSourceName атомы для эффектов, требующих источников).
Вы тогда добавляете описание эффекта к носителям дорожки эффекта.
Требуемые атомы описания эффектов
Существует несколько требуемых атомов, которые должно содержать описание эффекта. Первое kParameterWhatName атом. kParameterWhatName атом содержит имя эффекта. Это указывает который из доступных эффектов использовать.
Фрагмент кода, показанный в Перечислении 6-10, добавляет a kParameterWhatName атом к контейнеру атома effectDescription. Константа kCrossFadeTransitionType содержит имя плавно накладывать эффекта.
Перечисление 6-10 , добавляющее a kParameterWhatName атом к контейнеру атома effectDescription
effectCode = kCrossFadeTransitionType; |
QTInsertChild(effectDescription, kParentAtomIsContainer, |
kParameterWhatName, kParameterWhatID, 0, |
sizeof(effectCode), &effectCode, nil); |
В дополнение к kParameterWhatName атом, описание эффекта для эффекта, использующего источники, должны содержать один или больше kEffectSourceName атомы. Каждый из этих атомов содержит имя одного из источников эффекта. Входная карта используется для отображения этих имен к фактическим дорожкам фильма, которые являются источниками. Создание Входной Карты описывает, как создать входную карту.
Атомы параметра описания эффектов
В дополнение к требуемым атомам описание эффектов содержит переменное число атомов параметра. Число и типы атомов параметра варьируются от эффекта до эффекта. Например, крест исчезают, эффект имеет только один параметр, в то время как общий эффект фильтра свертки имеет девять. Некоторые эффекты не имеют никаких параметров вообще и не требуют никаких атомов параметра.
Можно получить список атомов параметра для проведенного в действие путем вызова компонентного использования эффекта ImageCodecGetParameterList. Атомы описания параметра, которые это возвращает, включают настройки по умолчанию для каждого параметра в форме атомов параметра, которые можно вставить в описание эффекта.
QTInsertChild функция используется для добавления этих параметров к описанию эффекта, как замечено в примере кода в Перечислении 6-10.
Рассмотрите, например, эффект нажатия. Его описание эффекта содержит a kParameterWhatName атом, два kEffectSourceName атомы и два атома параметра, один из которых является промежуточным кадром.
kParameterWhatName атом указывает, что это - a 'push' эффект.
Два kEffectSourceName атомы указывают два источника, которые этот эффект будет использовать в этом случае 'srcA' и 'srcB'. Имена соответствуют записям во входной карте дорожки эффекта.
'pcnt' атом параметра определяет, какие кадры эффекта показаны. Этот параметр содержит запись промежуточного кадра, так, чтобы значение этого параметра было интерполировано, когда работает эффект. Интерполяция 'pcnt' параметр заставляет последовательные кадры эффекта быть представленными, создавая эффект нажатия.
'from' параметр определяет направление нажатия. Этот параметр устанавливается из списка перечисления, с 2 определяемый как нижняя часть экрана.
В этом примере, источнике 'srcB' продвинет в от нижней части, покрывая источник 'srcA'.
'pcnt' параметр обычно вставляется промежуточные кадры от 0 до 100, так, чтобы эффект представил полностью, от 0 до 100 процентов. В этом примере, 'pcnt' параметр вставлен промежуточные кадры от 25 до 75, таким образом, эффект запустит 25 процентов пути через (с 'srcB' уже частично на экране) и конец 75 процентов пути через (с частью 'srcA' все еще видимый).
Рисунок 6-5 показывает набор атомов, которые должны быть добавлены к описанию записи.

Важное свойство параметров эффекта - то, что большинство может быть вставлено промежуточные кадры (и некоторые должны быть вставлены промежуточные кадры). Вставка промежуточных кадров является механизмом интерполяции QuickTime общего назначения (см. Носители Промежуточного кадра для получения дополнительной информации). Для многих параметров желательно позволить значению параметра изменяться, поскольку выполняется эффект. В примере, показанном на рисунке 6-5, 'pcnt' параметр должен быть промежуточным кадром. Эти средства управления параметром, которыми кадр эффекта представляется в любой момент времени, таким образом, это должно измениться для эффекта развиться. 'from' параметр не является промежуточным кадром в примере выше, но это могло быть, если бы мы хотели, чтобы направление нажатия изменилось в течение эффекта.
Создание входной карты
Входная карта является другим контейнером атома QT, который Вы присоединяете к дорожке эффектов. Это описывает источники, используемые в эффекте, и дает имя к каждому источнику. Это имя используется для обращения к источнику в описании эффектов.
Входная карта работает дружно со ссылочными атомами дорожки в исходных дорожках. Ссылочный атом дорожки типа kTrackModifierReference добавляется к каждой исходной дорожке, заставляющей тот исходный вывод дорожки быть перенаправленным к дорожке эффектов. Входная карта добавляется к дорожке эффектов, чтобы идентифицировать исходные дорожки и дать имя к каждому источнику, такой как 'srcA' и 'srcB'. Эффект может тогда относиться к источникам по имени, указывая это 'srcB' должен задвинуть 'srcA', например.
Структура входной карты
Входная карта содержит ряд атомов, относящихся к дорожкам, используемым в качестве источников для эффекта. Каждая исходная дорожка представлена одним ссылочным атомом дорожки типа kTrackModifierInput.
Каждый входной атом модификатора содержит два дочерних элемента, один из типа kEffectDataSourceType, и один из типа kTrackModifierType, которые содержат имя и тип источника.
Имя источника является уникальным идентификатором, который Вы создаете, который используется в описании эффекта для ссылки на дорожку. Любое четыре имени персонажа допустимы, пока это уникально в наборе исходных имен.
Дочерний атом типа kTrackModifierType указывает тип ссылаемой дорожки. Для видеотрека тип VideoMediaType, для дорожки спрайта это SpriteMediaType, и т.д. Видеотреки являются наиболее распространенным типом дорожки, используемым в качестве источников для эффектов. Только дорожки, имеющие видимый вывод, такой как видео и дорожки спрайта, могут использоваться в качестве источников для эффекта. Это означает, например, что звуковые дорожки не могут быть источниками для эффекта.
Рисунок 6-6 показывает завершенную входную карту, это ссылается на два источника. Первый источник является видеотреком и вызывается 'srcA'. Второй источник, также видеотрек, вызывают 'srcB'.
Вы обращаетесь к a kTrackModifierInput атом его индексом, возвращающимся AddTrackReference функционируйте при создании атома.

Создание входных карт
Первый шаг в создании входной карты должен создать новое QTAtomContainer содержать карту. Вы используете стандартную функцию создания контейнера QuickTime.
QTNewAtomContainer(&inputMap); |
Для каждого источника Вы создаете, необходимо вызвать AddTrackReference функция. Дорожка IDs дорожки эффектов и исходной дорожки передается как параметры AddTrackReference, который создает атом типа kTrackModifierReference и возвращает индекс. Вы используете этот индекс в качестве ID атома, когда необходимо обратиться к нему. Вы тогда вставляете ссылку во входную карту как атом типа kTrackModifierInput.
Код в Перечислении 6-11 создает ссылку на дорожку firstSourceTrack, и добавляет его к входной карте.
Перечисление 6-11 , Добавляющее входной ссылочный атом к входной карте
AddTrackReference(theEffectsTrack, firstSourceTrack, |
kTrackModifierReference, &referenceIndex); |
QTInsertChild(inputMap, kParentAtomIsContainer, |
kTrackModifierInput, referenceIndex, 0, 0, nil, &inputAtom); |
QTInsertChild функционируйте возвращает смещение нового входного атома модификатора в inputAtom параметр.
Теперь необходимо добавить имя и тип исходной дорожки к входному атому модификатора. Снова, вызов QTInsertChild функция делает это, как показано в следующем фрагменте кода:
inputType = VideoMediaType; |
QTInsertChild(inputMap, inputAtom, |
kTrackModifierType, 1, 0, sizeof(inputType), &inputType, |
nil); |
aType = 'srcA'; |
QTInsertChild(inputMap, inputAtom, kEffectDataSourceType, 1, 0, |
sizeof(aType), &aType, nil); |
Этот процесс повторяется для каждого источника для эффекта.
Создание фильмов с дорожками модификатора
QuickTime 2.1 добавил дополнительную функциональность для обработчиков носителей. Посредством дорожек модификатора обработчик носителей может отправить свои данные в другой обработчик носителей вместо того, чтобы представить его носители непосредственно. Посмотрите Дорожки Модификатора для полного обсуждения этой функции.
Для создания фильма с дорожками модификатора сначала Вы создаете фильм со всеми желаемыми дорожками, тогда Вы создаете дорожку модификатора. Для соединения дорожки модификатора с дорожкой, которую это изменяет Вы используете AddTrackReference функционируйте как показано в Перечислении 6-12.
Перечисление 6-12 , Соединяющее модификатор, отслеживает к дорожке, которую оно изменяет
long addedIndex; |
AddTrackReference(aVideoTrack, aModifierTrack, |
kTrackModifierReference, &addedIndex); |
Ссылка не полностью описывает отношение дорожки модификатора к дорожке, которую это изменяет. Вместо этого ссылка просто говорит дорожке модификатора отправлять свои данные в указанную дорожку. Дорожка получения не «знает» то, что она должна сделать с теми данными. Одноколейный путь может также получать данные больше чем от одной дорожки модификатора.
Чтобы описать, как каждый ввод модификатора должен использоваться, носители каждой дорожки также имеют входную карту. Входная карта носителей описывает, как данные, отправляемые в каждый ввод дорожки, должны быть интерпретированы дорожкой получения. После создания ссылки необходимо обновить входную карту носителей дорожки получения. Когда AddTrackReference вызывается, это возвращает индекс добавленной ссылки. Тот индекс является индексом ввода, который должен быть описан во входной карте носителей. Если дорожка модификатора, создаваемая выше, содержит области для изменения формы видеотрека, код, показанный в Перечислении 6-13, обновляет входную карту соответственно.
Перечисление 6-13 , Обновляющее входную карту
QTAtomContainer inputMap; |
QTAtom inputAtom; |
OSType inputType; |
Media aVideoMedia = GetTrackMedia(aVideoTrack); |
GetMediaInputMap (aVideoMedia, &inputMap); |
QTInsertChild(inputMap, kParentAtomIsContainer, kTrackModifierInput, |
addedIndex, 0,0, nil, &inputAtom); |
inputType = kTrackModifierTypeClip; |
QTInsertChild (inputMap, inputAtom, kTrackModifierType, 1, 0, |
sizeof(inputType), &inputType, nil); |
SetMediaInputMap(aVideoMedia, inputMap); |
QTDisposeAtomContainer(inputMap); |
Входная карта носителей позволяет Вам хранить дополнительную информацию для каждого ввода. В предыдущем примере только указан тип ввода. В других типах ссылок Вы, возможно, должны указать дополнительные данные.
Когда дорожка модификатора играет пустое редактирование дорожки, или отключена или удалена, все дорожки получения уведомляются, что ввод дорожки неактивен. Когда ввод становится неактивным, он сбрасывается к его значению по умолчанию. Например, если дорожка получает данные от дорожки модификатора клипа, и тот ввод становится неактивным, форма дорожки возвращается к форме, которую это имело бы, если бы не было никакой дорожки модификатора клипа.
Авторская разработка фильмов с внешними целями фильма
QuickTime 4 включает Вам к фильмам автора с внешними целями фильма. Для указания действия, предназначающегося для элемента внешнего фильма необходимо идентифицировать внешний фильм или его именем или его ID. Два новых целевых типа атома были представлены с этой целью; эти атомы используются в дополнение к существующим целевым атомам, которые можно использовать, чтобы указать, что элемент является определенной дорожкой или объектом в дорожке, такой как спрайт.
Эти дополнительные целевые атомы обеспечили в QuickTime 4:
[(ActionTargetAtoms)] = |
<kActionTarget> |
<kTargetMovieName> |
[Pstring MovieName] |
OR |
<kTargetMovieID> |
[long MovieID] |
OR |
[(kExpressionAtoms)] |
Для тегирования фильма с именем или ID Вы добавляете пользовательский элемент данных типа'plug'к пользовательским данным фильма. Индекс пользовательских данных не имеет значения. Данные указывают имя или ID.
Вы добавляете пользовательский элемент данных типа'plug'к пользовательским данным фильма с его набором данных к
"Movieid=MovieName" |
где MovieName имя фильма.
Вы добавляете пользовательский элемент данных типа 'plug'к пользовательским данным фильма с его набором данных к
"Movieid=MovieID" |
где ID является длинным целым со знаком.
Плагин QuickTime дополнительно поддерживает EMBED параметры тегов, позволяющие Вам переопределять имя фильма или ID в странице HTML.
Атомы Target для встроенных фильмов
QuickTime 4.1 представил целевые атомы для размещения добавления встроенных фильмов. Эти целевые атомы допускают пути, которые будут указаны в иерархическом дереве фильма.
Фильмы Target могут быть внешним фильмом, фильмом по умолчанию или любым фильмом, встроенным в другом фильме. Цели указаны при помощи пути фильма, который может включать родительские и дочерние отношения фильма и может дополнительно включать целевые атомы отслеживаемого и отслеживаемого объекта по мере необходимости.
При помощи встроенного kActionTarget атомы вместе с родительским и дочерним фильмом предназначаются для атомов, можно накопить пути для целей фильма. Обратите внимание на то, что QuickTime ищет, они встроили kActionTarget атомы только при оценке цели фильма и любого целевого типа фильма могут содержать одноуровневый элемент kActionTarget атом.
Пути начинаются с текущего фильма, который является фильмом, содержащим объект, обрабатывающий событие. Можно подняться дерево с помощью a kTargetParentMovie атом, или вниз дерево с помощью одного из пяти новых дочерних атомов фильма. Можно использовать a kTargetRootMovie атом как ярлык для получения до верхушки дерева, содержащей встроенный фильм и, может использовать movieByName и movieByID атомы для указания корневого внешнего фильма.
Целевые атомы:
kTargetRootMovie(листовой атом, никакие данные). Это - корневой фильм, содержащий обработчик действия.kTargetParentMovie(листовой атом, никакие данные). Это - родительский фильм.
Обратите внимание на то, что существует пять способов указать встроенный дочерний фильм. Три из них указывают свойства дорожки фильма. Два указывают свойства в настоящее время загруженного фильма в дорожке фильма.
kTargetChildMovieTrackName.Дочерняя дорожка фильма указана именем дорожки.kTargetChildMovieTrackID. Дочерняя дорожка фильма, указанная дорожкой ID.kTargetChildMovieTrackIndex. Дочерняя дорожка фильма указана индексом дорожки.kTargetChildMovieMovieName. Дочерний фильм указан именем фильма в настоящее время загруженного фильма. Дочерний фильм должен содержатьmovieNameпользовательские данные с указанным именем.kTargetChildMovieMovieID. Дочерний фильм, указанный фильмом в настоящее время загруженного фильма ID. Дочерний фильм должен содержатьmovieIDпользовательские данные с указанным ID.
Создание видеотреков в 30 кадрах в секунду
Продолжительность видеокадра сохранена в атоме времени к выборке, содержавшем в демонстрационном табличном атоме. Эта продолжительность не может быть интерпретирована без масштаба времени носителей, определяющего модули в секунду в течение какого-то времени. В этом примере каждый кадр имеет ту же продолжительность, таким образом, атом времени к выборке имеет одну запись, применяющуюся ко всем видеокадрам в носителях.
Пока отношение между продолжительностью кадра и масштабом времени носителей остается 1:30, любая комбинация значений может использоваться в течение какого-то времени и масштаб времени. Большее масштаб времени короче максимальная продолжительность. Начиная с фильма значения по умолчанию к масштабу времени 600, это - большое количество для использования. Это - также наименьшее общее кратное для 24, 25, и 30, делая его удобным для большой части математики, с которой Вы, вероятно, встретитесь при создании фильма.
Масштаб времени фильма независим от масштаба времени носителей. Так как Вы хотите избежать редактирований фильма, не приземляющихся на границы кадра, это - хорошая идея сохранить масштаб времени фильма и масштаб времени носителей тем же, или масштаб времени фильма должен быть ровным кратным числом масштаба времени носителей. Масштаб времени фильма сохранен в атоме заголовка фильма.
С масштабом времени 600 в атоме заголовка носителя, атом времени к выборке содержал бы значения данных, перечисленные в Таблице 6-1.
Поле | Значение |
|---|---|
Размер Atom |
24 |
Тип Atom |
|
Версия/Флаги |
0 |
Число записей |
1 |
Демонстрационное количество |
n |
Демонстрационная продолжительность |
20 |
Создание видеотреков в 29.97 кадрах в секунду
NTSC окрашивает, видео не является 30 кадрами в секунду (кадр/с), но фактически 29,97 кадр/с. Предыдущий пример показал, как масштаб времени носителей и продолжительность кадров указывают частоту кадров видео. Путем установки масштаба времени носителей в 2 997 модулей в секунду и установки продолжительностей кадра в 100 модулей каждый, действующая ставка составляет 29,97 кадр/с точно.
В этой ситуации это - также хорошая идея установить масштаб времени фильма в 2 997 во избежание редактирований фильма, не приземляющихся на границы кадра. Масштаб времени фильма сохранен в атоме заголовка фильма.
С масштабом времени 2 997 в атоме заголовка носителя, атом времени к выборке содержал бы значения данных, перечисленные в Таблице 6-2.
Поле | Значение |
|---|---|
Размер Atom |
24 |
Тип Atom |
|
Версия/Флаги |
0 |
Число записей |
1 |
Демонстрационное количество |
n |
Демонстрационная продолжительность |
100 |
Создание Звуковых дорожек в 44,1 кГц
Продолжительность аудиосэмпла сохранена в атоме времени к выборке, содержавшемся в демонстрационном табличном атоме. Эта продолжительность не может быть интерпретирована без масштаба времени носителей, определяющего модули в секунду в течение какого-то времени. С аудио продолжительность каждого аудиосэмпла обычно равняется 1, таким образом, атом времени к выборке имеет одну запись, применяющуюся ко всем аудиосэмплам.
С масштабом времени 44 100 в атоме заголовка носителя, атом времени к выборке содержал бы значения данных, перечисленные в Таблице 6-3.
Поле | Значение |
|---|---|
Размер Atom |
24 |
Тип Atom |
|
Версия/Флаги |
0 |
Число записей |
1 |
Демонстрационное количество |
n |
Демонстрационная продолжительность |
1 |
Этот атом не указывает, является ли аудио стерео или моно или содержит ли это 8-разрядные или 16-разрядные выборки. Та информация хранится в звуковом демонстрационном атоме описания, содержащемся в демонстрационном табличном атоме.
Создание дорожки временного кода для видео на 29,97 футов в секунду
Дорожка временного кода указывает информацию о временном коде для других дорожек. Временной код отслеживает временные коды первоисточника видео и аудио. После того, как фильм был отредактирован, временной код может быть извлечен для определения исходной ленты и временных кодов кадров.
Важно, чтобы дорожка временного кода имела тот же масштаб времени как видеотрек. Иначе, временной код не отсчитает в то же самое время как видеотрек.
Для каждого непрерывного исходного сегмента ленты существует единственная выборка временного кода, указывающая значение временного кода, соответствующее запуску сегмента. От этой выборки значение временного кода может быть определено для любой точки в сегменте.
Демонстрационное описание для дорожки временного кода указывает используемую систему временного кода (например, кадр отбрасывания на 30 кадр/с) и информация об источнике. Каждая выборка является значением временного кода.
Так как обработчик носителей временного кода является полученным из основного обработчика носителей, атом информации о носителях запускается с универсального атома заголовка носителя. Атомы временного кода содержали бы следующие значения данных:
Размер Atom |
80 |
||
Тип Atom |
|
||
Размер Atom |
24 |
||
Тип Atom |
|
||
Версия/Флаги |
0 |
||
Графический режим |
0x0040 |
||
(Красный) Opcolor |
0x8000 |
||
(Зеленый) Opcolor |
0x8000 |
||
(Синий) Opcolor |
0x8000 |
||
Баланс |
0 |
||
Зарезервированный |
0 |
||
Размер Atom |
48 |
||
Тип Atom |
|
||
Размер Atom |
40 |
||
Тип Atom |
|
||
Версия/Флаги |
0 |
||
Шрифт текста |
0 (системный шрифт) |
||
Текстовая поверхность |
0 (плоскость) |
||
Размер текста | 12 | ||
Дополнение |
0 |
||
(Красный) цвет текста |
0 |
||
(Зеленый) цвет текста |
0 |
||
(Синий) цвет текста |
0 |
||
(Красный) цвет фона |
0 |
||
(Зеленый) цвет фона |
0 |
||
(Синий) цвет фона |
0 |
||
Имя шрифта |
|
Демонстрационный табличный атом содержит все стандартные демонстрационные атомы и имеет следующие значения данных:
Размер Atom |
174 |
||
Тип Atom |
|
||
Размер Atom |
74 |
||
Тип Atom |
|
||
Версия/Флаги |
0 |
||
Число записей |
1 |
||
Демонстрационный размер описания [1] |
58 |
||
Формат данных [1] |
|
||
Зарезервированный [1] |
0 |
||
Индекс [1] ссылки на данные |
1 |
||
Флаги [1] |
0 |
||
Флаги (временной код) [1] |
7 (отбрасывают кадр + 24-часовой + отрицательные времена OK), |
||
Масштаб времени [1] |
2997 |
||
Продолжительность кадра [1] |
100 |
||
Число кадров [1] |
20 |
||
Размер Atom |
24 |
||
Тип Atom |
|
||
Длина строки |
12 |
||
Код языка |
0 (английский язык) |
||
Имя |
“мое имя ленты” |
||
Размер Atom |
24 |
||
Тип Atom |
|
||
Версия/Флаги |
0 |
||
Число записей |
1 |
||
Демонстрационное количество [1] |
1 |
||
Демонстрационная продолжительность [1] |
1 |
||
Размер Atom |
28 |
||
Тип Atom |
|
||
Версия/Флаги |
0 |
||
Число записей |
1 |
||
Первый блок [1] |
1 |
||
Выборки на блок [1] |
1 |
||
Демонстрационное описание ID [1] |
1 |
||
Размер Atom |
20 |
||
Тип Atom |
|
||
Версия/Флаги |
0 |
||
Объем выборки |
4 |
||
Число записей |
1 |
||
Размер Atom |
20 |
||
Тип Atom |
|
||
Версия/Флаги |
0 |
||
Число записей |
1 |
||
Смещение [1] |
(смещение в файл блока 1) |
В примере давайте предположим, что временной код начала сегмента является 1:15:32.4 (1 час, 15 минут, 32 секунды и 4 кадра). Время было бы выражено в файле данных как 0x010F2004 (0x01 = 1 час; 0x0F = 15 минут; 0x20 = 32 секунды; 0x04 = 4 кадра).
Видеотреки и звуковые дорожки должны содержать ссылочный атом дорожки, чтобы указать, что они ссылаются на эту дорожку временного кода. Ссылка дорожки является тем же для обоих и содержится в атоме дорожки (на том же уровне как заголовок дорожки и атомы носителей).
Эта ссылка дорожки содержала бы значения данных, перечисленные в Таблице 6-4.
Поле | Значение |
|---|---|
Размер Atom |
12 |
Тип Atom |
|
Ссылочный тип |
|
Отследите ID дорожки, на которую ссылаются (дорожка временного кода) |
3 |
В этом примере видеотреки и звуковые дорожки являются дорожками 1 и 2. Дорожка временного кода является дорожкой 3.
Игра со списками редактирования
Сегмент фильма может быть повторен, не копируя данные носителей при помощи списков редактирования. Предположим, что у Вас есть однодорожечный фильм, масштаб времени носителей которого равняется 100, и продолжительность дорожки 1000 (10 секунд). Для этого примера масштаб времени фильма 600. Если бы нет никаких редактирований в фильме, атом редактирования содержал бы значения данных, перечисленные в Таблице 6-5.
Размер Atom |
36 |
|
Тип Atom |
|
|
Размер Atom |
28 |
|
Тип Atom |
|
|
Версия/Флаги |
0 |
|
Число записей |
2 |
|
Продолжительность дорожки |
6000 (10 секунд) |
|
Время носителей |
0 |
|
Уровень носителей |
1.0 |
Поскольку это - однодорожечное перемещение, продолжительность дорожки в атоме заголовка дорожки 6000, и продолжительность фильма в атоме заголовка фильма 6000.
При изменении дорожки, чтобы играть носители со времени 0 ко времени 2 секунды, и затем играть носители со времени 0 ко времени 10 секунд, атом редактирования теперь содержал бы эти значения данных:
Размер Atom |
48 |
|
Тип Atom |
|
|
Размер Atom |
40 |
|
Тип Atom |
|
|
Версия/Флаги |
0 |
|
Число записей |
2 |
|
Продолжительность дорожки [1] |
1200 (2 секунды) |
|
Время носителей [1] |
0 |
|
Уровень носителей [1] |
1.0 |
|
Продолжительность дорожки [2] |
6000 (10 секунд) |
|
Время носителей [2] |
0 |
|
Уровень носителей [2] |
1.0 |
Поскольку дорожка является теперь 2 секундами дольше, продолжительность дорожки в атоме заголовка дорожки должна теперь быть 7200, и продолжительность фильма в атоме заголовка фильма должна также быть 7200.
В настоящее время, игры носителей со времени 0 ко времени 2, затем играет со времени 0 ко времени 10. Если Вы берете тот повторный сегмент вначале (время 0 ко времени 2) и играете его в удвоенной скорости для поддержания исходной продолжительности, атом редактирования теперь содержал бы следующие значения:
Размер Atom |
60 |
|
Тип Atom |
|
|
Размер Atom |
52 |
|
Тип Atom |
||
Версия/Флаги |
0 |
|
Число записей |
3 |
|
Продолжительность дорожки [1] |
600 (1 секунда) |
|
Время носителей [1] |
0 |
|
Уровень носителей [1] |
2.0 |
|
Продолжительность дорожки [2] |
600 (1 секунда) |
|
Время носителей [2] |
0 |
|
Уровень носителей [2] |
2.0 |
|
Продолжительность дорожки [3] |
4800 (8 секунд) |
|
Время носителей [3] |
200 |
|
Уровень носителей [3] |
1.0 |
Поскольку дорожка теперь вернулась к своей исходной продолжительности 10 секунд, ее продолжительность в атоме заголовка дорожки 6000, и продолжительность фильма в атоме заголовка фильма 6000.
Чередование данных фильма
Для получения оптимального воспроизведения фильма необходимо создать фильм с чередованными данными. Поскольку данные для фильма помещаются в диск в порядке времени, данные в течение определенного времени в фильме находятся близко друг к другу в файле. Это означает, что необходимо вкрапить данные от различных дорожек. Для иллюстрирования этого рассмотрите фильм с единственным видео и единственной звуковой дорожкой.
Рисунок 6-7 показывает, как данные фильма были собраны, и как данные должны будут быть воспроизведены для надлежащей синхронизации. В этом примере видеоданные зарегистрированы в 10 кадрах в секунду, и аудиоданные сгруппированы в полувторые блоки.

После того, как данные были чередованы на диске, атом данных фильма будет содержать данные фильма в порядке, показанном на рисунке 6-8.

В этом примере файл начинается с атома фильма ('moov'), сопровождаемый атомом данных фильма ('mdat'). Для преодоления любых задержек в воспроизведении звука по крайней мере одна секунда звуковых данных помещается в начале чередованных данных. Это означает, что звуковые и видеоданные смещаются друг от друга в файле на одну секунду.
Ссылка на два файла данных с одноколейным путем
Индекс ссылки на данные, который будет использоваться для данной выборки носителей, сохранен в демонстрационном описании той выборки. Поэтому дорожка должна содержать многократные демонстрационные описания для той дорожки для ссылки на многократные файлы данных. Различное демонстрационное описание должно использоваться каждый раз, когда файл данных изменяется или каждый раз, когда изменяется формат данных. Атом выборки к блоку определяет который демонстрационное описание использовать для выборки.
Демонстрационный атом описания содержал бы следующие значения данных:
Размер Atom |
… |
|
Тип Atom |
|
|
Версия/Флаги |
0 |
|
Число записей |
2 |
|
Демонстрационный размер описания [1] |
… |
|
Формат данных |
|
|
Зарезервированный |
0 |
|
Индекс ссылки на данные |
1 |
|
(демонстрационные данные) |
… |
|
Демонстрационный размер описания [1] |
… |
|
Формат данных |
|
|
Зарезервированный |
0 |
|
Индекс ссылки на данные |
2 |
|
(демонстрационные данные) |
… |
Если существует только 1 выборка на блок, и первые 10 выборок извлечены из демонстрационного описания 2, и следующие 30 выборок извлечены из демонстрационного описания 1, атом выборки к блоку содержал бы следующие значения данных:
Размер Atom |
40 |
Тип Atom |
|
Версия/Флаги |
0 |
Число записей |
2 |
Первый блок [1] |
1 |
Выборки на блок [1] |
1 |
Демонстрационное описание ID [1] |
2 |
Первый блок [2] |
11 |
Выборки на блок [2] |
1 |
Демонстрационное описание ID [2] |
1 |
Атом ссылки на данные содержал бы следующие значения данных:
Размер Atom |
… |
|
Тип Atom |
|
|
Размер Atom |
… |
|
Тип Atom |
|
|
Версия/Флаги |
0 |
|
Число записей |
2 |
|
Размер [1] |
… |
|
Тип [1] |
|
|
Версия [1] |
0 |
|
Флаги [1] |
0 (не сам ссылаемый) |
|
Ссылка на данные [1] |
[псевдоним, указывающий на файл № 1] |
|
Размер [2] |
… |
|
Тип [2] |
|
|
Версия [2] |
0 |
|
Флаги [2] |
0 (не сам ссылаемый) |
|
Ссылка на данные [2] |
[псевдоним, указывающий на файл № 2] |
Получение имени QuickTime узел VR
Можно использовать стандартные функции контейнера атома QuickTime для получения информации в QuickTime атом заголовка узла VR. Например, MyGetNodeName функция, определяемая в Перечислении 6-14 возвращает имя узла учитывая его узел ID.
Перечисление 6-14 , Получающее имя узла
OSErr MyGetNodeName (QTVRInstance theInstance, UInt32 theNodeID, |
StringPtr theStringPtr) |
{ |
OSErr theErr = noErr; |
QTAtomContainer theNodeInfo; |
QTVRNodeHeaderAtomPtr theNodeHeader; |
QTAtom theNodeHeaderAtom = 0; |
//Get the node information atom container. |
theErr = QTVRGetNodeInfo(theInstance, theNodeID, &theNodeInfo); |
//Get the node header atom. |
if (!theErr) |
theNodeHeaderAtom = QTFindChildByID(theNodeInfo, kParentAtomIsContainer, |
kQTVRNodeHeaderAtomType, 1, nil); |
if (theNodeHeaderAtom != 0) { |
QTLockContainer(theNodeInfo); |
//Get a pointer to the node header atom data. |
theErr = QTGetAtomDataPtr(theNodeInfo, theNodeHeaderAtom, nil, |
(Ptr *)&theNodeHeader); |
//See if there is a name atom. |
if (!theErr && theNodeHeader->nameAtomID != 0) { |
QTAtom theNameAtom; |
theNameAtom = QTFindChildByID(theNodeInfo, kParentAtomIsContainer, |
kQTVRStringAtomType, theNodeHeader->nameAtomID, nil); |
if (theNameAtom != 0) { |
VRStringAtomPtr theStringAtomPtr; |
//Get a pointer to the name atom data; copy it into the string. |
theErr = QTGetAtomDataPtr(theNodeInfo, theNameAtom, nil, |
(Ptr *)&theStringAtomPtr); |
if (!theErr) { |
short theLen = theStringAtomPtr->stringLength; |
if (theLen > 255) |
theLen = 255; |
BlockMove(theStringAtomPtr->string, &theStringPtr[1], theLen); |
theStringPtr[0] = theLen; |
} |
} |
} |
QTUnlockContainer(theNodeInfo); |
} |
QTDisposeAtomContainer(theNodeInfo); |
return(theErr); |
} |
MyGetNodeName функция, определяемая в Перечислении 6-14 получает контейнер атома информации об узле (путем вызова QTVRGetNodeInfo) и затем взгляды в том контейнере для атома заголовка узла с атомом ID 1. Если это находит один, это блокирует контейнер и затем получает указатель на данные атома заголовка узла. Желаемая информация, имя узла, содержится в строковом атоме, атом которого ID указан nameAtomID поле структуры заголовка узла. Соответственно, MyGetNodeName функционируйте тогда вызывает QTFindChildByID еще раз найти тот строковый атом. Если строковый атом найден, MyGetNodeName вызовы QTGetAtomDataPtr получить указатель на строковые данные атома. Наконец, MyGetNodeName копирует строковые данные в надлежащее расположение и очищает после себя перед возвратом.
Добавление пользовательских атомов в QuickTime фильм VR
При авторской разработке QuickTime фильм VR можно принять решение добавить пользовательские атомы или к миру VR или к контейнерам атома информации об узле. Те атомы могут быть извлечены в приложении для предоставления дополнительной информации, которую может использовать приложение.
Информация, принадлежащая всей сцене, могла бы храниться в пользовательском атоме в контейнере атома мира VR. Специфичная для узла информация могла храниться в отдельных контейнерах атома информации об узле или как одноуровневые атомы к атомам расположения узла в мире VR.
Пользовательские атомы горячей точки должны быть сохранены как одноуровневые элементы к атомам информации о горячей точке в контейнере атома информации об узле. Обычно его тип атома совпадает с пользовательским типом горячей точки. Можно установить процедуру прерывания в приложении для обработки, щелкает по пользовательским горячим точкам.
При использовании пользовательских атомов необходимо установить процедуру прерывания горячей точки при открытии фильма. Перечисление 6-15 является примером такой процедуры прерывания.
Перечисление 6-15 Типичная процедура прерывания горячей точки
QTVRInterceptProc MyProc = NewQTVRInterceptProc (MyHotSpot); |
QTVRInstallInterceptProc (qtvr, kQTVRTriggerHotSpotSelector, myProc, 0, 0); |
pascal void MyHotSpot (QTVRInstance qtvr, QTVRInterceptPtr qtvrMsg, |
SInt32 refCon, Boolean *cancel) |
{ |
UInt32 hotSpotID = (UInt32) qtvrMsg->parameter[0]; |
QTAtomContainer nodeInfo = |
(QTAtomContainer) qtvrMsg->parameter[1]; |
QTAtom hotSpotAtom = (QTAtom) qtvrMsg->parameter[2]; |
OSType hotSpotType; |
CustomData myCustomData; |
QTAtom myAtom; |
QTVRGetHotSpotType (qtvr, hotSpotID, &hotSpotType); |
if (hotSpotType != kMyAtomType) return; |
// It's our type of hot spot - don't let anyone else handle it |
*cancel = true; |
// Find our custom atom |
myAtom = QTFindChildByID (nodeInfo, hotSpotAtom, kMyAtomType, 1, nil); |
if (myAtom != 0) { |
OSErr err; |
// Copy the custom data into our structure |
err = QTCopyAtomDataToPtr (nodeInfo, myAtom, false, |
sizeof(CustomData), &myCustomData, nil); |
if (err == noErr) |
// Do something with it |
DoMyHotSpotStuff (hotSpotID, &myCustomData); |
} |
} |
Для Вашей процедуры прерывания вызывают, щелкает по любой горячей точке. Необходимо проверить, чтобы видеть, является ли это тип горячей точки и, если так, извлеките пользовательский атом горячей точки и сделайте то, что является подходящим для типа горячей точки (DoMyHotSpotStuff).
Когда Вам больше не нужна процедура прерывания, необходимо вызвать QTVRInstallInterceptProc снова с тем же селектором и a nil указатель процедуры и затем вызывает DisposeRoutineDescriptor на myProc.
Apple резервирует всю горячую точку и типы атома со строчными буквами. Ваш пользовательский тип горячей точки должен содержать все прописные буквы.
Добавление контейнеров Atom в QuickTime фильм VR
Принятие Вас уже создало QuickTime мир VR и контейнеры атома информации об узле, Вы использовали бы код (минус проверка ошибок) Перечисление 6-16 для добавления их к дорожке QTVR.
Перечисление 6-16 , Добавляющее контейнеры атома к дорожке
long descSize; |
QTVRSampleDescriptionHandle qtvrSampleDesc; |
// Create a QTVR sample description handle |
descSize = sizeof(QTVRSampleDescription) + GetHandleSize((Handle) vrWorld) - |
sizeof(UInt32); |
qtvrSampleDesc = (QTVRSampleDescriptionHandle) NewHandleClear (descSize); |
(*qtvrSampleDesc)->size = descSize; |
(*qtvrSampleDesc)->type = kQTVRQTVRType; |
// Copy the VR world atom container data into the QTVR sample description |
BlockMove (*((Handle) vrWorld), &((*qtvrSampleDesc)->data), |
GetHandleSize((Handle) vrWorld)); |
// Now add it to the QTVR track's media |
err = BeginMediaEdits (qtvrMedia); |
err = AddMediaSample (qtvrMedia, (Handle) nodeInfo, 0, |
GetHandleSize((Handle) nodeInfo), duration, |
(SampleDescriptionHandle) qtvrSampleDesc, 1, 0, &sampleTime); |
err = EndMediaEdits (qtvrMedia); |
InsertMediaIntoTrack (qtvrTrack, trackTime, sampleTime, duration, 1L<<16); |
duration значение вычислено на основе продолжительности соответствующих выборок дорожки изображения для узла. Значение trackTime время в течение начала текущего узла (нуль для единственного фильма узла). Значения duration и sampleTime находятся в основе времени носителей; значение trackTime находится в основе времени фильма.
Оптимизация QuickTime фильмы VR для веб-воспроизведения
Первоначально, оба фильма в формате QuickTime и QuickTime, фильмы VR должны были быть полностью загружены к локальному жесткому диску пользователя, прежде чем они могли быть просмотрены. Начиная с QuickTime 2.5, если данные фильма должным образом размечаются в файле, стандартные линейные фильмы в формате QuickTime могут быть просмотрены почти сразу. Кадры, загруженные до сих пор, показаны, в то время как последующие кадры продолжают быть загруженными.
Важное изменение, имевшее место, чтобы позволить этому происходить, было для QuickTime для размещения глобальной информации о фильме в начале файла. Первоначально, эта информация была в конце файла. После этого данные кадра просто должны быть в порядке в файле. Точно так же файлы VR QuickTime также должны быть размечены определенным способом для получения своего рода быстрой обратной связи при просмотре в сети. Грубо говоря это включает выписывание всех выборок носителей в файле в определенном порядке. Apple теперь обеспечивает, фильм экспортируют компонент, делающий это для Вас: Рихтовочный инструмент QTVR.
Рихтовочный инструмент QTVR
Рихтовочный инструмент QTVR является компонентом экспорта фильма, преобразовывающим существующий QuickTime VR единственный фильм узла в новый фильм, оптимизированный для сети. Мало того, что рихтовочный инструмент переупорядочивает выборки носителей, но и для обзоров, он также создает маленький предварительный просмотр обзора. Когда просматривается в сети, этот предварительный просмотр появляется после 5% к 10% данных фильма был загружен, позволив пользователям видеть версию более низкого разрешения обзора.
Используя рихтовочный инструмент QTVR из Вашего приложения довольно просто. После создания QuickTime фильм VR Вы просто открываете компонент QTVR Flattener и вызываете MovieExportToFile подпрограмма как показано в Перечислении 6-17.
Перечисление 6-17 Используя рихтовочный инструмент
ComponentDescription desc; |
Component flattener; |
ComponentInstance qtvrExport = nil; |
desc.componentType = MovieExportType; |
desc.componentSubType = MovieFileType; |
desc.componentManufacturer = QTVRFlattenerType; |
flattener = FindNextComponent(nil, &desc); |
if (flattener) qtvrExport = OpenComponent (flattener); |
if (qtvrExport) |
MovieExportToFile (qtvrExport, &myFileSpec, myQTVRMovie, nil, 0, 0); |
Фрагмент кода, показанный в Перечислении 6-17, создает сглаженный файл ролика, указанный myFileSpec параметр. если Ваш QuickTime размер четверти, размытый JPEG, сжатый предварительный просмотр изображения обзора, фильм VR является обзором, сглаженный файл ролика включает
Можно подарить пользователям собственное диалоговое окно Рихтовочного инструмента QTVR, чтобы позволить им выбирать опции такой в качестве, как сжать изображение предварительного просмотра или выбрать отдельный файл образа предварительного просмотра. Используйте следующий код для показа диалогового окна:
err = MovieExportDoUserDialog (qtvrExport, myQTVRMovie, nil, 0, 0, &cancel); |
Если пользователь отменяет диалоговое окно, то булева отмена установлена в true.
Если Вы не хотите дарить пользователю диалоговое окно рихтовочного инструмента, можно связаться непосредственно с компонентом при помощи MovieExportSetSettingsFromAtomContainer подпрограмма, как описано в следующих параграфах.
Если Вы хотите указать изображение предварительного просмотра кроме значения по умолчанию, необходимо создать специальный контейнер атома и затем вызвать MovieExportSetSettingsFromAtomContainer перед вызовом MovieExportToFile. Можно указать, как сжать изображение, какое разрешение использовать, и можно даже указать собственный файл образа предварительного просмотра, который будет использоваться. Контейнер атома, в котором Вы передаете, может иметь различные атомы, указывающие определенные опции экспорта. Эти атомы должны все быть дочерними элементами рихтовочного инструмента, настройки порождают атом.
Атом разрешения предварительного просмотра является 16-разрядным значением, позволяющим Вам указывать разрешение изображения предварительного просмотра. Это значение, который значения по умолчанию к kQTVRQuarterRes, указывает, сколько сократить изображение предварительного просмотра.
Атом предварительного просмотра размытости является булевым значением, указывающим, размыть ли изображение перед сжатием. Размывание обычно приводит к намного более очень сжатому изображению. Значение по умолчанию true.
Создать атом предварительного просмотра является булевым значением, указывающим, должно ли быть создано изображение предварительного просмотра. Значение по умолчанию true.
Атом предварительного просмотра импорта является булевым значением, использующимся, чтобы указать, что изображение предварительного просмотра должно быть импортировано из внешнего файла, а не сгенерировано от изображения в самом файле обзора. Это позволяет Вам иметь любое изображение, которое Вы хотите как предварительный просмотр для обзора. Можно указать, каким файлом использовать также включая атом спецификации импорта, который является FSSpec структура данных, идентифицирующая файл образа. Если Вы не включаете этот атом, то рихтовочный инструмент дарит пользователю диалоговое окно, прося, чтобы пользователь выбрал файл. Значение по умолчанию для предварительного просмотра импорта false. Если файл импорта используется, изображение используется в его естественном размере, и настройка разрешения проигнорирована.
Демонстрационный контейнер Atom для рихтовочного инструмента QTVR
Пример кода в Перечислении 6-18 создает контейнер атома и добавляет атомы для указания файла предварительного просмотра импорта для рихтовочного инструмента для использования.
Перечисление 6-18 , Указывающее файл предварительного просмотра для рихтовочного инструмента для использования
Boolean yes = true; |
QTAtomContainer exportData; |
QTAtom parent; |
err = QTNewAtomContainer(&exportData); |
// create a parent for the other settings atoms |
err = QTInsertChild (exportData, kParentAtomIsContainer, |
QTVRFlattenerParentAtomType, 1, 0, 0, nil, &parent); |
// Add child atom to indicate we want to import the preview from a file |
err = QTInsertChild (exportData, parent, QTVRImportPreviewAtomType, 1, 0, |
sizeof (yes), &yes, nil); |
// Add child atom to tell which file to import |
err = QTInsertChild (exportData, parent, QTVRImportSpecAtomType, 1, 0, |
sizeof (previewSpec), &previewSpec, nil); |
// Tell the export component |
MovieExportSetSettingsFromAtomContainer (qtvrExport, exportData); |
Переопределение настроек сжатия немного более сложно. Необходимо открыть стандартный диалоговый компонент сжатия изображений и выполнить вызовы для получения контейнера атома, который можно тогда передать компоненту QTVR Flattener.
Перечисление 6-19 , Переопределяющее настройки сжатия
ComponentInstance sc; |
QTAtomContainer compressorData; |
SCSpatialSettings ss; |
sc = OpenDefaultComponent(StandardCompressionType,StandardCompressionSubType); |
ss.codecType = kCinepakCodecType; |
ss.codec = nil; |
ss.depth = 0; |
ss.spatialQuality = codecHighQuality |
err = SCSetInfo(sc, scSpatialSettingsType, &ss); |
err = SCGetSettingsAsAtomContainer(sc, &compressorData); |
MovieExportSetSettingsFromAtomContainer (qtvrExport, compressorData); |