Václav Kadlec 22.3.2005
Dnešní díl seriálu se pořád týká empétrojek a technologie jejich rozšíření o textové informace - ID3 tagů. Dostaneme se však k samotnému jádru věci: podíváme se na to, jak vypadají samotné datové rámce ID3v2 tagu. V těch jsou totiž uloženy samotné informace, kterými chceme empérojku nebo jiný hudební soubor obohatit.
Dnešní článek je dalším pokračováním série dokumentů o formátu a struktuře ID3v2 tagu, které představují technologii pro rozšíření hudebních souborů o textové (a nejen textové) informace.
Ve dvou předchozích článcích jsme se podrobněji zabývali dokumentem z URL http://www.id3.org/id3v2.4.0-structure.txt, který obsahuje podrobnou specifikaci ID3v2 tagů. Podívejme se na to, co jsme si o zmíněné technologii doposud prozradili:
Ještě než se pustíme do samotné náplně dnešního dílu, podívejme se opět na to, jak ID3v2 tag vlastně vypadá. Obecná struktura je zde:
+--------------------------------------+
|
Hlavička (Header) - 10 bajtů
|
+--------------------------------------+
| Rozšířená hlavička (Extended
Header) |
| (proměnná délka,
NEPOVINNÁ)
|
+--------------------------------------+
|
Rámce (Frames) |
|
(proměnná délka)
|
+--------------------------------------+
|
Padding
|
| (proměnná délka,
NEPOVINNÁ)
|
+--------------------------------------+
|
Patička (Footer)
|
| (10 bajtů,
NEPOVINNÁ)
|
+--------------------------------------+
Pokud se na schéma pozorně zadíváte, možná si všimnete, že už jsme rozebrali všechny jeho součásti, až na jednu, a to tu nejdůležitější. Už totiž víme všechno o "začátcích" a "koncích" tagu, tedy o hlavičkách, rozšířených hlavičkách, paddingu a patičkách, nicméně tyto sekce se vlastně nijak netýkají samotného obsahu tagu. Jinak řečeno, dosud nevíme nic o tom, jak jsou v tagu uložena samotná požadovaná textová (nebo i binární) data.
Tato data jsou totiž součástí "prostřední" sekce tagu, a to sekce rámců. V úvodních dílech věnovaných tagům ID3v2 jsme si řekli, že rámců může být v tagu víc; v závislosti na tom, jaké informace (a jaké druhy informací) chceme do tagu uložit, použijeme odpovídající počet rámců a naplníme je požadovanými informacemi.
A práve popis a rozbor rámců bude součástí dnešního článku. Pojďme na to!
Jak jsme si již prozradili, rámce jsou hlavní součástí tagů, neboť právě ony obsahují samotné informace, které jsou hlavní náplní příslušného tagu. Lze si to představit také tak, že ID3v2 tag, který je umístěn kdesi v souboru (podrobnostmi o umístění tagu v empétrojce se budeme zabývat později) je jakýmsi kontejnerem, který obsahuje části popsané v dřívějších kapitolách (všemožné hlavičky, rozšířené hlavičky, patičky apod.) a který ve svém prostředku obsahuje nějaký počet obálek, přičemž každá obálka je naplněna papírem s jedním druhem informací; můžeme tedy mít obálku s textem písničky, další obálku s informacemi o interpretovi, další s názvem alba apod. Analogie obálky a rámce je myslím zřejmá.
Všechny rámce (obálky) v ID3v2 tagu můžeme dále rozčlenit na několik jejich vnitřních sekcí. Rámec obsahuje vlastní hlavičku následovanou jedním nebo více poli obsahujícími již samotné informace.
Hlavička rámce (pozor, nezaměňte prosím s hlavičkou celého tagu, kterou jsme se zabývali kdysi předminule) je vždy přesně 10 bajtů dlouhá a vypadá takhle:
Frame ID $xx xx xx xx (čtyři znaky)
Size 4 * %0xxxxxxx
Flags $xx xx
Frame ID je vytvořen čtyřmi znaky (velká písmena A-Z a číslice 0-9). Existuje určité omezení říkající, že identifikátory začínající písmeny "X", "Y" a "Y" jsou určeny pro experimentální použití, ale já bych to na tomto místě zbytečně nerozebíral.
Frame ID je následováno informací o velikosti rámce. Tato hodnota nezapočítává velikost hlavičky (jinak řečeno, celková velikost kompletního rámce je o 10 bajtů větší než uvedené číslo) a je uloženo jako 32bitový tzv. sychsafe (viz později) integer.
Za informací o velikosti obsahuje hlavička dva bajty určené pro příznaky různých vlastností (tzv. flagy). V následujícím textu se podíváme na to, jaké flagy jsou k dispozici a k čemu slouží.
Ještě předtím si však povězme, jaká jsou obecná pravidla pro flagy. Všechny nepoužité flagy musí být vymazány (nastaveny na nulu). První bajt je určen pro "status message" (zpráva o stavu), druhý bajt je pak popisovačem formátu. Pokud je v prvním bajtu nastaven neznámý flag, nesmí být rámec nijak změněn bez toho, aby byl příslušný neznámý flag vymazán (nastaven na nulu). Pokud je neznámý flag nastaven ve druhém bajtu, bude celý rámec s největší pravděpodobností nečitelný. Některé flagy ve druhém bajtu indikují, že k hlavičce framu jsou přidány nějaké speciální informace. Pole s těmito speciálními informacemi jsou uloženy ve stejném pořadí jako flagy, které je indikují.
Pole s flagy je definováno takto (písmena "l" a "o" jsou vynechána z toho důvodu, že se příliš podobají jedničkám a nulám):
%0abc0000 %0h00kmnp
Některé flagy v popisovači formátu indikují, že k rámci jsou připojeny dodatečné informační položky. Tyto položky jsou přidány za hlavičku rámce, avšak před data rámce, samozřejmě ve stejném pořadí jako flagy, které je indikují.
Nejprve se pojďme podívat na flagy určené pro popis statusu rámce.
Flag a - co dělat s neznámým rámcem při změně tagu
Tento flag říká parseru, co má dělat s neznámým rámcem v případě, kdy je celý tag jakkoliv modifikován, změněn. Týká se to všech druhů modifikace, tedy třeba i přidání dalšího paddingu, změny pořadí rámců apod. Možné hodnoty:
0 - rámec má být zachován,
1 - rámec má být zahozen.
Flag b - co dělat s neznámým rámcem při změně souboru
Tento flag je podobný flagu a. Jeho nastavením totiž říkáme parseru, co má dělat s neznámým rámcem v případě, kdy je celý soubor (s vyloučením tagu ovšem) změněn. Týká se to všech druhů modifikace souboru s jedinou výjimkou: pokud jsou celá, kompletní audiodata nahrazena jinými audiodaty.Možné hodnoty flagu:
0 - rámec má být zachován,
1 - rámec má být zahozen.
Flag c - rámec je read-only
Flag c použijeme, pokud chceme říci jakémukoliv zpracovávajícímu softwaru, že obsah rámce je určen pouze pro čtení. V některé situaci se totiž může stát, že modifikací obsahu bychom udělali něco nepěkného, například porušili podpis apod. Pokud se rozhodneme změnit obsah rámce nastaveného na read-only, aniž bychom věděli, proč byl nastaven na read-only, a aniž bychom se přesvědčili, že jsme provedli všechny potřebné kompenzace a nápravy plynoucí ze změny, máme povinnost nastavit tento flag na nulu.
Tím jsme vyčerpali všechny tři tagy určené pro popis statusu rámce. Druhý bajt v poli flagů je určen pro popis formátu rámce.
Flagů pro popis formátu aktuálního rámce je pět.
Flag h - seskupení rámců
Vzhledem k povaze rámců je pravděpodobné, že se čas od času dostaneme do situace, v níž by se nám hodilo seskupit (alespoň logicky) více rámců, které popisují související informace, do jedné skupiny. Právě k tomu slouží flag h, jehož prostřednictvím lze přiřadit rámce do logických skupin.
Flag h tedy indikuje, zda aktuální rámec náleží nebo nenáleží do některé skupiny rámců. Pokud je flag nastaven, je do rámce následně přidán bajt identifikující skupinu - tzv. group identifier byte. Všechny rámce s totožným group identifier bajtem samozřejmě náleží do téže skupiny rámců. Možné hodnoty flagu jsou velmi nepřekvapivé:
0 - rámec nenáleží do žádné skupiny a tedy neobsahuje žádný group identifier
bajt
1 - rámec je součástí skupiny a obsahuje bajt s jejím identifikátorem
Flag k - komprese
Tento flag říká, zda rámec je a nebo není komprimován. Pokud ano, musí rámec obsahovat informaci o skutečné délce dat, tzv. Data Length Indicator. Možné hodnoty flagu:
0 - rámec není komprimován
1 - rámec je komprimován použitím zlib
algoritmu. Nastavením tohoto flagu na hodnotu 1 vzniká povinnost nastavit Data
Lenght Indicator bit také na hodnotu 1.
Flag m – šifrování
Pomocí tohoto flagu můžeme říci, že obsah rámce je šifrován. Pokud je flag nastaven na jedničku, je rámec rozšířen o jeden bajt indikující metodu použitou při šifrování (podrobnosti souvisí s rámcem ENCR, viz později). Šifrování by v žádném případě nemělo být provedeno po kompresi.
Flag n - unsynchronization
Tento flag je opravdu zajímavý. Možná si při čtení následujících řádků vzpomenete, že jsme se tohoto problému před časem již dotkli. Flag n totiž indikuje, zda byla nebo nebyla na rámec použita tzv. "unsynchronization". Podrobnosti o tomto mechanismu si povíme později, nyní pouze naznačím, že pokud je flag nastaven, jsou všechny data nacházející se mezi koncem hlavičky rámce až do konce rámce "unsynchronizovaná". Přítomnost indikátoru délky dat (výše zmíněný Data Length Indicator) není povinná, je však doporučená.
Flag p - indikátor délky dat
Konečně se dostáváme k flagu, o kterém jsme se zmínili snad už pětkrát. Indikátor délky dat (Data length indicator) nastavený na jedničku indikuje, že k rámci je připojena informace o délce dat obsažených v rámci. Informace o délce dat přitom může být popsána jako "délka rámce v případě, že všechny flagy rámce jsou nastaveny na nulu" (neobsahuje tedy délku žádných dodatečných dat). Údaj je reprezentován jako 32 sychsafe integer.
Čtenáři tohoto seriálu se na mě často obracejí a ukazují mi svá dílka a projekty, které vznikly na základě informací ze seriálu a nebo se nějak týkají jeho aktuální náplně. Protože jde často o kvalitní a téměř vždy o zajímavé počiny, pokusím se na ty nejlepší upozornit přímo v rámci seriálu, aby se na ně mohli podívat (a případně se z nich poučit) i ostatní.
Tuto informaci zároveň vezměte jako výzvu, abyste mě informovali o svých programech, které jste případně vytvořili po přečtení některého z dílů seriálu.
Před nedávnem jsem anoncoval možnosti prohlížení offline verze seriálu, dnes vás nasměruji na projekt pana Jiřího Činčury, který vytvořil zajímavý software pro práci s ID3 tagy. Zajímají-li vás podrobnosti, navštivte prosím stránky projektu.
Dnešní článek začal rozebírat datové rámce ID3v2 tagů. V rámcích jsou uložena samotná data, kterými chceme empétrojku nebo jiný hudební soubor obohatit. Vzhledem k flexibilnosti technlogie ID3v2 existuje celá řada různých způsobů, jak může datový rámec vypadat a jaké informace může obsahovat. K definování podrobností o rámcích slouží tzv. flagy a právě ty jsme si dnes vysvětlili.
Příště povídání o rámcích ID3v2 tagů dokončíme.