Контейнеры.

Автор: Юрий Ревич
Опубликовано в   журнале "Домашний Компьютер" №3 от 3 марта 2008 года

Контейнерами в объектно-ориентированных языках программирования называются специальные структуры, внутри которых единообразным способом могут быть представлены различные типы данных. Хорошим примером использования контейнеров может служить язык разметки HTML, в котором каждая страничка, по сути, есть один большой контейнер, начинающийся с тега <html> и заканчивающийся тегом </html>. В него могут быть вложены контейнеры заголовка (<head>..</head >), тела документа (<body>..</body>) и т. д.

История контейнеров — мифы и рифы

В 1985 году знаменитая фирма-производитель видеоигрушек Electronic Arts совместно с фирмой Commodore, выпустившей прославленный игровой компьютер Amiga, специально для этой платформы разработали стандарт — Interchange File Format, формат файлов обмена, IFF. Это был первый медиаконтейнер, который мог содержать звук, графику, анимацию, текст и т. п. (о видео тогда, видимо, речь еще не шла). Структура файлов в этом стандарте предполагала разбиение их на блоки (названные создателями chunks — ломти), каждый из которых состоял из заголовка и собственно данных. Заголовок определял, как следует интерпретировать данные: не давал алгоритма их обработки, про который предполагалось, что он уже имеется где-то в системе, а лишь указывал, какой из алгоритмов следует в данном случае использовать и в какой конкретной его интерпретации.

Идеология построения контейнеров из таких кирпичиков с легкой руки создателей IFF стала потом общепринятой. На основе канонического IFF созданы такие известные форматы, как Microsoft Word, MIDI, DjVu или PNG. Созвучный по названию растровый формат TIFF также заимствовал общий принцип, хотя от канонического IFF отличается. Наиболее известен вариант IFF под названием RIFF (Resource Interchange File Format), который стал базовым для представления потоковых медиаданных — среди наиболее популярных RIFF-контейнеров AVI и WAV. Канонический RIFF имеет ограничение по размеру файла в 2 Гбайта (из-за того, что для указания позиции в файле используется 32-битное число со знаком, которое и дает максимальное положительное значение 2 147 483 648 байт), чего в принципе хватает для большинства нужд, кроме видео. Для поддержки видеофайлов большого размера формат AVI был расширен до AVI-DV, но, как утверждает «Википедия», это уже не совсем RIFF.

Понятие «контейнер» стало употребляться и применительно к форматам хранения разнородных данных в едином файле. Существенный признак контейнера — то, что формат хранения данных внутри него не задается строго определенным и единственным образом. Например, растровый формат TIFF — контейнер, в котором собственно картинка (или картинки — например, отдельные слои одного изображения) может храниться в виде несжатого двоичного массива пикселей, сжиматься различными алгоритмами (включая JPEG в нескольких вариантах), быть представлена в различных моделях цветности, сопровождаться различными служебными слоями (сохраняющими полупрозрачную маску или контур обтравки) и т. д. Типичные контейнеры — это форматы DOC (Microsoft Word), PDF, RTF, DjVu и другие разновидности представления тексто-графической информации, где в одном файле может сохраняться текст с элементами форматирования, таблицы, графика (как векторная, так и растровая) или другие виды информации (тот же звук). Однако, если вам встретился этот термин без дополнительных пояснений, то скорее всего имеются в виду так называемые медиаконтейнеры для представления видео- и аудиоданных. К самым известным медиаконтейнерам относятся MP4 (не путать с форматом сжатия видеоинформации MPEG-4), QuickTime, OGG, Flash (да-да, тот самый, который раньше Macromedia, а ныне Adobe Flash), AVI. Для чистого аудио наиболее известен контейнер WAV.

Подчеркнем, что форматы хранения или сжатия данных (MP3 или AAC для звука, как и MPEG-1/2/4 или, к примеру, кодек H.264 для видео) — это еще не контейнеры. Так, и QuickTime, и AVI одинаково могут использовать любой из перечисленных форматов хранения данных в своем составе.

Давайте на примере популярных потоковых форматов AVI и WAV рассмотрим поподробнее медиаконтейнеры, а также коснемся текстовых контейнеров.

Audio Video Interleave — AVI

Формат AVI можно представить как чередование видео и аудио. Мы познакомились с ним, когда Microsoft в ноябре 1992 года впервые выпустила пакет Video for Windows. С тех пор AVI стал базовым для хранения видео в Windows.

AVI (вместе с QuickTime Apple и развиваемой «опенсорсниками» системой Matroska) относится к числу наиболее универсальных контейнеров: в нем может встречаться почти любое сочетание форматов хранения видео и аудио. В этом его отличие от таких более специализированных контейнеров, как, например, MP4 (предназначенного для представления видео в MPEG-4 в сочетании с различными форматами звука ). В этом же объяснение его долголетия и одновременно его недостаток — не все устройства воспроизведения одинаково хорошо «разбираются» в вариантах AVI.

Простые аудио- и видеопотоки могут содержаться в AVI-файле без какого-либо сжатия, и такой формат до сих пор используется для небольших (менее минуты) клипов с невысоким разрешением. Для полноформатных AVI-видеороликов в настоящее время особой популярностью пользуется такая пара: DivX (для видео) и WMA (для аудио). Информация о кодеке может содержаться в AVI-файле, и при открытом доступе в Интернет последние версии Windows Media Player умеют сами обращаться на сайт Microsoft и скачивать (при его наличии там) необходимый кодек. В частности, по этой причине воспроизведение разноформатного видео программными плеерами в компьютерах обычно доставляет меньше хлопот, чем запуск роликов через «железные» плееры, в которых нужного кодека может попросту не оказаться.

В первых байтах AVI-файла всегда содержится информация о контейнере: «RIFF <размер области данных> AVI». После них должно идти как минимум два блока, начинающихся со слова LIST: блок заголовка ‘hdrl’ и блок данных ‘movi’. В заголовке хранятся данные, определяющие форматы потоков, располагающихся в области ‘movi’.

Канонический AVI был заточен под хранение видео в отдельных кадрах, к каждому из которых полагалось свое звуковое сопровождение. Такой кадр мог храниться в виде обычного несжатого изображения в формате BMP, а звук — также несжатого WAV. Конечно, кроме BMP, предусмотрено и хранение со сжатием (если использовался JPEG, то такая последовательность кадров образует формат Motion JPEG). Но применение форматов сжатия MPEG, где на отдельные кадры картинка не разбивается, заставило отойти от этой простой схемы.

Заметим, что фотокамеры, способные работать в режиме съемки видео, часто используют нестандартные контейнеры, потому снятые ролики приходится перекодировать с помощью различных программ. Так, некоторые DVD-проигрыватели воспроизводят видео в MPEG-4 только в контейнере AVI и «не понимают» контейнеры MP4, применяющиеся, например, в некоторых камерах Olympus, Sanyo или Sony. Есть и другие случаи несовместимости. Для перекодировки в «нормальный» формат годится любая «продвинутая» программа видеомонтажа (например Ulead VideoStudio), есть и специализированные бесплатные программы, такие, как MP4Cam2AVI или Avi2DVD.

Waveform Audio File Format — WAV

В отличие от AVI, формат «волновых колебаний» предназначен только для аудио. Для него первоначально подразумевалось, что звук записывается несжатым, но были предусмотрены и различные звуковые форматы со сжатием.

Самые первые байты в файле WAV, аналогично AVI, — это идентификатор формата «RIFF <размер области данных> WAVEfmt». Так же, как и в случае других контейнеров, опознавание происходит именно по этим байтам, потому расширение имени файла может быть любым: у меня на компьютере хранятся файлы с записями песен Высоцкого с расширением mp3, и, что самое интересное, по сути таковыми и являются. Но зачем-то авторам записей понадобилось обычный MP3 еще упаковать в контейнер WAV, так что плееры не обманываются, правильно идентифицируя эти файлы как WAV, хранящий звук в сжатом формате MP3.

В простейшем случае после идентификационного заголовка в WAV-файле указывается размер и формат данных (на что отведено 24 байта), в том числе приводится величина битрейта (сколько отсчетов в секунду), количество каналов (моно или стерео) и т. п. Затем следует ключевое слово data, после чего располагаются собственно данные. Если формат — без сжатия, то эти данные могут представлять 8-битный (по байту на каждый отсчет) или 16-битный (по два байта на отсчет) звук. Если число каналов более одного, то отсчеты для каждого располагаются друг за другом, причем первым идет левый канал, вторым — правый. Столь простая структура позволяет использовать WAV-файлы для хранения последовательностей оцифрованного сигнала не только для аудионадобностей, но и других (например научно-технических) целей.

Разумеется, файлы с таким представлением звука без компрессии получаются «неподъемными» (примитивный диктофон с 8-битным монофоническим звуком и битрейтом 8 тыс. отсчетов в секунду потребует примерно 30 Мбайт дискового пространства на каждый час записи, а нормальный 16-битный стереозвук CD-качества — уже около полугигабайта в час). Потому сколько-нибудь длинные записи в несжатом формате не встречаются: используется вариант с компрессией. В таких более сложных случаях WAV-файлы включают дополнительные заголовки и структуры: в них указывается не только кодек, но и содержатся данные о правах копирования и другая дополнительная информация.

Теперь остановимся на популярных текстовых файлах-контейнерах, которые кроме текста могут содержать и графическую информацию в различной форме — Microsoft Word и RTF. Стоило бы рассмотреть еще один из самых популярных контейнеров — Adobe PDF (близкий родственник «языка описания страниц» PostScript), но в силу его сложности и громоздкости посвятим этому отдельный рассказ.

DOC

Представление текста в RTF

Собственно текст может непосредственно храниться в RTF, но, начиная с версии формата 1.6 (1999 год), это допускается лишь для латинских символов, цифр и некоторых знаков (пробела, запятой, точки и пр.). При этом находящиеся в тексте знаки перевода строки, как и в HTML, игнорируются, работают лишь управляющие слова \раr (может заменяться последовательностью \10 или \13) и \line. Есть специальные управляющие символы для некоторых специальных знаков (например, знак неразрывного пробела \~ или мягкого переноса \-).

Знаки, выходящие за пределы 128 символов «канонического» ASCII, должны быть также представлены в форме управляющих последовательностей. Подавляющая часть RTF-файлов использует однобайтовую (\ansi) кодировку с одновременным указанием языка в форме \ansicpgN, где N — кодовая страница (1251 для кириллицы). В одном документе можно мешать языки, объявляя для соответствующего фрагмента каждый раз свою кодовую страницу. В таком представлении каждый знак, например, русского текста предваряется «обратным слэшем», после чего идет управляющий символ в виде прямого апострофа «‘» и код буквы в шестнадцатеричной форме: например, \’c5 означает заглавную русскую «Е».

Использование двухбайтовой кодировки Unicode предусмотрено в более поздних версиях формата, причем несколькими способами, простейший из которых — после «слэша» идет управляющий символ u, затем десятичный номер символа.

Форматов Microsoft Word, как известно, существует несколько, причем самым распространенным пока остается Word 97–2003 (с расширением DOC), отличающийся от более старого Word 6.0 в основном тем, что в нем текст представлен в двухбайтовой кодировке Unicode. Файлы в формате DOC начинаются с идентификатора (числовой сигнатуры), которая в шестнадцатеричной форме выглядит, как D0 CF 11 E0. Эта сигнатура представляет собой одно 32-битное число, в обычной десятичной форме выглядящее как 3 759 263 696 (или –535 703 600, если представлять его, как число со знаком). На самом деле она не является эксклюзивным идентификатором для DOC-формата, потому что DOC есть лишь частный случай «составных файлов» (compound file) в рамках технологий OLE/COM/ActiveX, имеющих в принципе одинаковую структуру и читающихся с помощью одних и тех же программных библиотек (файлы Excel также начинаются с этой сигнатуры).

Файлы, подобные DOC, — это довольно сложное структурированное хранилище, в определенной степени напоминающее структуру каталогов в дисковой файловой системе FAT (даже минимальные размеры блоков данных совпадают с размером дискового сектора и равны обычно 512 байтам). В таком файле имеется корневой каталог («корневое хранилище»), указывающий на то, в каких секторах расположены различные данные и каталоги, описывающие вложенные структуры.

Описание формата для Word 8 (Word 97) было фирмой Microsoft опубликовано, но за кадром осталось множество недокументированных возможностей (злые языки утверждают, что и в самой Microsoft в них не полностью разбираются). Все последующие дополнения формата открыто не публиковались. Потому большинство работающих с форматом DOC сторонних программ обладает лишь ограниченной совместимостью с оригинальными DOC-файлами.

Две особенности DOC-формата стали притчей во языцах: это, во-первых, способность содержать в своем составе созданные пользователем программы-макросы, во-вторых, сохранять различные изменения, которым подвергался документ в процессе работы над ним. Первое стало причиной появления макровирусов, способных заражать систему (последнее время, правда, макровирусы несколько «вышли из моды», но беречься от них все равно следует). А вот второе даже не очень понятно зачем сделано — штатных средств прочесть сохраненные изменения, если это специально не задано в процессе редактирования, в Word’е нет, зато извлечь их сторонними программами не составляет особого труда. И это не раз служило источником конфузов для пиар-отделов различных фирм, когда из невинного пресс-релиза досужие журналюги извлекали конфиденциальную информацию.

Начиная с Word 2003, параллельно с обычным DOC стал вводиться формат, основанный на универсальном языке разметки XML, и в Office 2007 он стал основным. XML — это тоже контейнер, но, в отличие от проприетарного DOC, — открытый. Microsoft даже пыталась сделать свой формат, основанный на XML, стандартом документов в рамках ISO (в чем ей, впрочем, пока отказано).

RTF

В отличие от DOC, RTF (Rich Text Format — «расширенный текстовый формат») основан не на каких-то там специальных OLE-структурах, а представляет собой независимый от платформы текстовый документ, подобно HTML размеченный специальными служебными словами-тегами (в терминологии RTF их называют управляющими словами и управляющими символами). В силу отсутствия каких-либо исполняемых кодов, он, в частности, не может нести в себе вирусы. Начинается он всегда с последовательности {\rtf, которая служит его отличительным признаком.

RTF — это классический контейнер с вложенными друг в друга контейнерами помельче. Каждый такой контейнер обычно начинается с управляющего слова или символа, предваряемого знаком «обратный слэш». Например, последовательность \раr задает начало абзаца, \line — перевод строки (без образования нового абзаца), \deffn — означает, что должен использоваться шрифт по умолчанию и т. д. Управляющие слова либо действуют до следующего знака того же назначения, либо перед ним может идти открывающая фигурная скобка, которой где-то обязательно должна соответствовать закрывающая — так получают область действия управляющего слова, в том числе во вложенных управляющих последовательностях. Например, последовательность «\par {\i Курсив} обычный текст {\b жирный {\i жирный курсив}}.\par» отобразится в отдельном абзаце, как «Курсив обычный текст жирный жирный курсив.» и завершится переводом на начало следующего абзаца.

В RTF могут внедряться таблицы и картинки, причем в последнем случае RTF-файл будет значительно большего объема, чем идентичный по содержанию DOC. Это происходит потому, что картинка там представлена в виде простого массива чисел без какого-либо сжатия, причем числа даны в текстовом формате, в шестнадцатеричной форме, что увеличивает объем еще ровно вдвое: так, число 10, занимающее один байт в памяти, будет записано, как два символа 0a.

Описание формата RTF всех версий можно скачать с сайта http://microsoft.com, но из-за всех этих тонкостей и огромного количества управляющих слов, со своей спецификой и вариантами представления, разобраться в RTF-файле «вручную», несмотря на всю кажущуюся логичность его построения, — мука мученическая.

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

Cплиттеры, кодеки и их коды

Распаковкой файлов-контейнеров занимается программа-сплиттер. Когда она доходит до конкретной реализации аудио- или видеопотока, в дело вступают кодеки — методы представления аудио- или видеопотока в различных форматах. Кодеком также называют не только сам метод кодирования, но и программу-драйвер, которая реализует этот метод. Кодеки не следует путать с собственно форматами сжатия: так, конвертировать аудио в формат MP3 можно с помощью абсолютно разных кодеков. Другой пример — единый стандарт MPEG-4, есть реализация разных возможностей в рамках этого стандарта, например DivX и AVC/H.264 (реализующие MPEG-4 Part 2 и Part 10, соответственно), а есть конкретные кодеки, которые это и делают на практике, но по-разному. Причем если вариантов кодеков DivX встречается лишь несколько, то собственных кодеков H.264 сейчас «не настрогал» только ленивый.

Как вы поняли из этого примера, различных кодеков, что в принципе делают одно и то же, встречается множество, и разобраться в них часто не под силу даже знатоку. Иногда сжатие может делаться разными кодеками, а вот воспроизводится результат практически любым того же назначения; реже кодеки оказываются несовместимыми и по воспроизведению. Положение усугубляется тем, что производители очень любят давать собственные наименования кодекам, которые по сути ничем не отличаются от более распространенных. Например, DIVX, DVX3, SAN3, XVID — кодеки, которые при воспроизведении файлов MPEG-4/DivX в подавляющем большинстве случаев дадут идентичный результат.

А вот программа-плеер запросто может «не понять», что от нее хотят. В используемом контейнере всегда указывается так называемый FourCC-код используемого кодека, например, в AVI он находится, начиная с байта номер 188 (BCh в шестнадцатеричной форме) от начала файла. Этот код всегда состоит из четырех знаков, на что указывает его название — Four Character Code (служебные слова в RIFF-контейнерах, такие, как LIST или собственно RIFF, это тоже FourCC-коды). Большинство встречающихся на практике FourCC-кодов для видеокодеков и некоторых других форматов можно найти на сайте http://fourcc.org. Причем для правильного распознавания кодека важен даже используемый регистр букв — так, DIVX и divx, формально говоря, относятся к разным кодекам.

Если видео в каком-то формате никак не желает воспроизводиться, то положение иногда может спасти универсальный кодек FFDshow, который не только поддерживает форматы DivX/XviD, H.264, WMV, MPEG 1 и 2 и еще кучу других, но и позволяет осуществлять тонкие настройки. Хорошую инструкцию по применению FFDshow можно найти на http://forum.sharereactor.ru/showthread.php?t=62337. Для тех, кто вообще не желает возиться с кодеками, отличным выбором может также стать «опенсорсный» Media Player Classic, отличающийся строгим «классическим» оформлением (по образцу старинного Windows Media Player 6), работающий в любой Windows, начиная с 95-й, не требующий инсталляции и воспроизводящий без проблем почти любое видео и аудио. Причем использовать такие универсалы предпочтительнее, чем скачивать наборы кодеков, вроде популярного K-Lite Codec Pack, в котором все доступные кодеки попросту свалены в кучу, и никогда точно неизвестно, насколько хорош сделанный вашей программой выбор. К тому же, если появился какой-то новый кодек, то K-Lite Codec Pack приходится опять скачивать и устанавливать целиком.

Наконец, есть программы, позволяющие попросту подменить название кодека (например, XVID на DIVX или DIVX на divx). К самым популярным из них относится заточенная под контейнер AVI программа FourCC Code Changer. А программа GSpot, скачать которую можно по адресу http://gspot.headbands.com, позволит диагностировать проблему: открыв в ней файл, можно узнать FourCC-код, название кодека и его наличие/отсутствие в системе.

Контейнеры