České vysoké učení technické v Praze Fakulta elektrotechnická
ˇ VUT FEL katedra pocˇı´tacˇu˚ C
Bakalářská práce
Přehrávač pro interaktivní video Mikuláš Krupička
Vedoucí práce: Berka Roman Ing., Ph.D.
Studijní program: Elektrotechnika a informatika strukturovaný bakalářský Obor: Informatika a výpočetní technika květen 2008
ii
Poděkování Rád bych poděkoval všem, kteří se podíleli na vzniku a implementaci a všem, kteří mne v této práci podporovali. Děkuji panu Ing. Romanu Berkovi Ph.D., svému vedoucímu práce za podporu. iii
iv
Prohlášení Prohlašuji, že jsem svou bakalářskou práci vypracoval samostatně a použil jsem pouze podklady uvedené v přiloženém seznamu. Nemám závažný důvod proti užití tohoto školního díla ve smyslu §60 Zákona č. 121/2000 Sb., o právu autorském, o právech souvisejících s právem autorským a o změně některých zákonů (autorský zákon).
V Praze dne 12.6. 2008
.............................................................
v
vi
Abstract The goal of the work was to study the possibilities and the structure of the MPEG-4 format and design and implement the architecture of interactive player of multichannel video with the possibility to play video forward and backward, smoothly change the playing speed and currently playing channel. The starting point were thesis of former students working on similar theme.
Abstrakt Cílem práce bylo prostudovat možnosti a strukturu formátu MPEG-4 a navrhnout a implementovat architekturu interaktivního přehrávače vícekanálového videa umožňujícího přehrávat video vpřed i vzad, plynule měnit rychlost i aktuálně přehrávaný kanál. Výchozím místem byly bakalářské práce předchůdců zpracovávajících obdobné téma.
vii
viii
Obsah Seznam obrázků
xi
Seznam tabulek
xiii
1 Úvod 1.1 Interaktivní video . . . . . . . 1.2 Historie interaktivního videa 1.2.1 Kinoautomat . . . . . 1.2.2 Full Motion Video . . 1.2.3 DVD, Blu-ray . . . . . 1.2.4 QuickTime VR . . . . 1.2.5 Immersive Media . . . 1.3 Motivace a záměr práce . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
1 1 1 1 1 2 2 2 3
2 Analýza a návrh řešení 2.1 Úvod . . . . . . . . . . . . . . . . 2.1.1 Základní pojmy . . . . . . 2.2 Vytváření interaktivního obsahu 2.3 Kontejner . . . . . . . . . . . . . 2.4 Informace o odbočení . . . . . . . 2.4.1 Uložení informací . . . . . 2.4.2 Formát souboru . . . . . . 2.4.3 Provedení odbočení . . . 2.5 Vstup od uživatele . . . . . . . . 2.6 Přehrávání pozpátku . . . . . . . 2.6.1 Zakódování snímků . . . . 2.6.2 Způsob načítání snímků . 2.7 Snímky za sekundu . . . . . . . . 2.8 Změna rychlosti . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
4 4 5 6 6 7 7 8 9 10 10 10 11 11 11
3 Realizace 3.1 Úvod . . . . . . . . . . . . . . . . . . . 3.1.1 Vývojové prostředky . . . . . . 3.1.2 Použité programy . . . . . . . . 3.1.3 Knihovna ffmpeg . . . . . . . . 3.2 Vlákna . . . . . . . . . . . . . . . . . . 3.2.1 Obecně . . . . . . . . . . . . . 3.2.2 Sdílené prostředky . . . . . . . 3.3 „Workerÿ vlákno . . . . . . . . . . . . 3.3.1 Požadavky ve vláknu Worker . 3.3.1.1 Zařazení požadavku . 3.3.1.2 Zpracování požadavků 3.3.2 FrameBuffer . . . . . . . . . . . 3.3.2.1 Práce s mutexem . . . 3.3.3 Přehrávání pozpátku . . . . . . 3.3.4 Odbočení . . . . . . . . . . . . 3.3.4.1 Zrušení skoku . . . . 3.3.4.2 Práce s mutexem . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . .
13 13 13 13 13 14 14 15 16 16 16 17 17 18 18 18 20 20
. . . . . . . .
ix
3.4
„Displayÿ vlákno . . . . . . . . . . . 3.4.1 Ovládání . . . . . . . . . . . 3.4.1.1 Klávesnice . . . . . 3.4.1.2 Gamepad . . . . . . 3.4.2 Zobrazení . . . . . . . . . . . 3.4.2.1 Snímky za sekundu 3.4.2.2 Vykreslování . . . .
4 Diskuze 4.1 Splněné požadavky . . . . . . 4.2 Co nebylo realizováno . . . . 4.3 Možné budoucí problémy . . 4.4 Možnosti rozšíření/vylepšení .
. . . .
. . . .
. . . .
. . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . .
21 21 21 22 23 23 24
. . . .
25 25 25 25 26
5 Závěr
27
6 Literatura
29
7 Příloha 7.1 Instalace a použití programu 7.1.1 Kompilace . . . . . . . 7.1.2 Instalace . . . . . . . . 7.1.3 Ovládání . . . . . . . 7.1.4 Obsah CD . . . . . . .
30 30 30 30 30 31
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
x
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Seznam obrázků 1.1 1.2
Snímek z filmu kinoautomat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Obrázek z interaktivního videa firmy Immersive Media . . . . . . . . . . . . . .
2.1 2.2 2.3 2.4 2.5
Video soubor - uživatelův pohled . . . . . . . . . Video soubor - skutečný stav . . . . . . . . . . . Nákres přehrávání obsahu formou server - klient Jednoduché schéma vnitřní struktury kontejneru Načítání snímků pro přehrávání pozpátku . . . .
. . . . .
4 4 8 9 11
3.1 3.2 3.3
Diagram funkce programu a vláken . . . . . . . . . . . . . . . . . . . . . . . . . Nákres funkce bufferu a jeho zaplnění . . . . . . . . . . . . . . . . . . . . . . . Automat odbočení . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14 18 19
xi
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
1 2
xii
Seznam tabulek 3.1 3.2
Ovládání pomocí klávesnice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ovládání pomocí gamepadu . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
xiii
21 22
xiv
1
KAPITOLA 1. ÚVOD
1 Úvod 1.1
Interaktivní video
Tímto pojmem obvykle označujeme spojení lineárního videa s možností jej určitým způsobem ovlivňovat. Jedná se například o jednoduché věci, jako menu na DVD discích, nebo o složitější, s určitou mírou volnosti přímo při přehrávání (viz. kapitola 1.2.5).
1.2 1.2.1
Historie interaktivního videa Kinoautomat
Za jednoho z prvních tvůrců interaktivního videa je pokládán režisér a technologický vizionář Radůz Činčera a jeho film Kinoautomat . V roce 1967 na výstavě EXPO ’67 uvedl právě tento film. Jeho interaktivita spočívala v zastavení v určitém napínavém momentu, před diváky poté vystoupil moderátor a dal jim na výběr, kterým směrem se má film ubírat dále. [8]
Obrázek 1.1: Snímek z filmu kinoautomat Nápadem podobný byl i televizní seriál Rozpaky kuchaře Svatopluka, uvedený v roce 1984. Při vysílání byl každý díl obdobným způsobem pozastaven a divákům dáno na výběr. Svoji volbu dávali najevo poměrně kuriózním způsobem: rozsvítili nebo zhasli v bytě světla a podle aktuální spotřeby energie se následně rozhodlo, jakým směrem bude seriál pokračovat dále. [7] 1.2.2
Full Motion Video
Dnes již v podstatě mrtvý formát, poprvé se objevil v roce 1983. [5] Používal se ve hrách určených pro konzole a jednalo se o předtočené scény uložené na digitálním disku. Těžil z tehdejší velmi špatně vypadající renderované grafiky na konzolích, předtočené scény vypadaly mnohem lépe. Avšak s rostoucím výkonem konzolí a jejich schopnosti renderovat reálné scény, tato technologie téměř vymizela. A to hlavně díky několika důvodům: • Takto produkované hry byly nesmírně nákladné. V tehdejší době stály stejně jako například nízkorozpočtový film. • Právě díky video obsahu byly také velmi náročné na velikost místa, kde byly uloženy (hra The X-Files: The Game byla distribuována na sedmi CD). • Nestandardnost formátů. Téměř každá společnost měla pro tuto technologii svůj vlastní formát a způsob zobrazování. Interaktivita byla přístupna pouze ve formě reakcí na uživatelovy podněty ze statické části hry. Hráč měl na příklad na monitoru statickou scénu, ve které když projevil nějakou akci, hra
2
KAPITOLA 1. ÚVOD
přehrála předpřipravenou sekvenci a následně se vrátila zpátky do statické části (třeba už v jiné scéně). Pozůstatky této technologie můžeme dnes spatřovat například ve videích uvozujících jednotlivé mise v počítačových hrách. Jejich interaktivita spočívá pouze ve více takto předpřipravených videí a následném výběru podle způsobu splnění úkolu hráčem. 1.2.3
DVD, Blu-ray
Video DVD disky byly poprvé uvedeny na trh v roce 1996 v Japonsku. Proti videokazetám VHS, které byly striktně lineární, nabídlo DVD omezenou, avšak velice vítanou interaktivitu. Byla to možnost členění do menu a více úrovní, volba kapitol, řetězení jednotlivých stop za sebe podle pokynů skriptu. Tento skript také mohl onu návaznost libovolně měnit. Z počátku byla také velmi zdůrazňována možnost mít na disku více různých obrazových stop a tak se moci na scénu během přehrávání dívat z různých úhlů. Pravděpodobě však kvůli technické náročnosti na přípravu takového materiálu se tato vlastnost nikdy komerčně nerozšířila. [9] Specifikace Blu-ray disk formátu byla dokončena v roce 2004 a uzavřena v roce 2006. Blu-ray disky posouvají onu dosti omezenou hranici interaktivity o kousek dále. Například u Blu-ray edice filmu Návrat do domu hrůzy má divák možnost zvolit si několikrát během filmu, jakým směrem se bude dále ubírat. Takto si může navolit až 96 různých obměn [4]. Bohužel, stále výběr probíhá tak, že diváka vytrhne ze sledování a nabídne mu volbu v klasickém menu. 1.2.4
QuickTime VR
Tuto technologii vyvinula firma QuickTime. [6] Jedná se o prostorovou reprezentaci obrázků, buď kubickou nebo cylindrickou. Uživatel je omezen na jeden bod, ze kterého se může rozhlížet do všech směrů. Tento formát je zvláště vhodný pro ukázkovou reprezentaci místností či panoramat. Ale vzhledem ke své orientaci na statickou scénu je také velmi silně omezen. Nic jiného než možnost rozhlížení z jednoho bodu vlastně neposkytuje. 1.2.5
Immersive Media
Tým lidí z firmy Immersive Media vyvinul video, během jehož přehrávání je možné se otáčet o 360◦ . [3] Je to velmi podobné předcházející technologii QuickTime VR a představuje už určitou interaktivitu. Nicméně ne ve formě, jaká je požadována, tedy možnost vybrat si nejen úhel pohledu, ale hlavně přímo následující děj přehrávaného obsahu.
Obrázek 1.2: Obrázek z interaktivního videa firmy Immersive Media
KAPITOLA 1. ÚVOD
1.3
3
Motivace a záměr práce
V současné době neexistuje standard interaktivního videa, který by byl dostatečně rozšířen. Cílem této práce je proto navrhnout řešení, které by bylo snadné na implementaci a rozšíření. Důraz je při tom kladen na zachování kompatibility se současným standardem MPEG-4. Součástí práce je také implementace základního přehrávače schopného nabídnout uživateli požadovanou interaktivitu.
4
KAPITOLA 2. ANALÝZA A NÁVRH ŘEŠENÍ
2 Analýza a návrh řešení Tato kapitola pojednává o navrhovaném řešení interaktivního videa. Jaká je struktura souboru a jak vypadají data, která informují přehrávač o interaktivitě.
2.1
Úvod
Navrhované řešení přehrávání interaktivního videa bude založeno na souboru s multimediálními daty a dodatečných informacích, které budou jednoznačně určovat propojení mezi přehrávanými daty a zajišťovat tak požadovanou interaktivitu.
Obrázek 2.1: Video soubor - uživatelův pohled Tento obrázek nasťiňuje, jak by měl vypadat výsledek pro uživatele. Ten se po spuštění videa ocitne na začátku první stopy, odkud se může pohybovat směrem vpřed i vzad. Když se dostane do vyznačené oblasti, může dále pokračovat v původním směru nebo může dát přehrávači pokyn pro odbočení. Ten pak plynule, aniž by uživatel musel vybírat nějaké možnosti z menu, přejde do druhé stopy, kde dále pokračuje.
Obrázek 2.2: Video soubor - skutečný stav Z předešlých nákresů lze usoudit, že skutečný návrh uspořádání dat se bude velmi lišit od uživatelova vjemu. Předpokládaná výsledná struktura dat je založena na uložení všech stop do jednoho kontejneru. V tom se bude přehrávač s pomocí informací o odbočování pohybovat a zobrazovat data uživateli.
KAPITOLA 2. ANALÝZA A NÁVRH ŘEŠENÍ
5
V kontejneru tedy bude libovolné množství stop a každá z nich bude představovat pro uživatele možný směr pohybu. Samotné tyto stopy ale nejsou nijak svázány, proto bude nutné navrhnout způsob předávání informací přehrávači, které stopy a v jakých místech jsou propojeny. Uživatel si pak bude moci vybrat, zda chce pokračovat v přehrávání aktuální stopy nebo zda chce přeskočit do stopy nové. Tím mu dáme možnost ovlivňovat následující odehrávaný děj. Uživatel sám ale do vnitřní struktury dat neuvidí, jemu se přehrávaný obsah bude zdát naprosto jednolitý. Před samotnou implementací bude potřeba rozhodnout a určit několik věcí. • jak je zvolené řešení problému proveditelné v reálném nasazení, možná úskalí • jaký formát multimediálního souboru bude použit pro ukládání streamů a dat okolo • formát a způsob ukládání informací o možnostech odbočení ve videu, jaká je možná budoucí rozšiřitelnost • jak bude implementováno přehrávání pozpátku a změna rychlosti, ovládání uživatelem • možnosti změny stopy v průběhu přehrávání, nutné podmínky 2.1.1
Základní pojmy
Pro pochopení následujícího textu je potřeba objasnit některé pojmy z oblasti multimédií. • stream - datový proud, stopa s multimediálními informacemi (pro nás většinou bude představovat video stream, může ale představovat i zvukovou stopu nebo stopu s titulky) • streamování - přehrávání videoobsahu přes síť, na klientském počítači nemusí být video dostupné najednou celé (přehrává se už v průběhu stahování) • kontejner - způsob uložení více streamů do jednoho souboru, zajišťuje jejich vzájemnou synchronizaci (nejčastěji představuje jednu video a audio stopu) • odbočení - zvolený termín pro přechod z jedné stopy do druhé, podle dodatečných informací specifikujících místo a cíl změny • frame - snímek, označení pro jeden obrázek, který při následném přehrávání (například 25 snímků za sekundu) vytváří dojem pohybu, základní způsob přehrávání videoobsahu
6
KAPITOLA 2. ANALÝZA A NÁVRH ŘEŠENÍ
2.2
Vytváření interaktivního obsahu
Je potřeba se nejprve zamyslet, zda navrhované řešení a jeho struktura je přístupné a vhodné pro reálné nasazení. Pro vytvoření interaktivního videa existují pouze dvě nutné podnímky: 1. Mít video materiál, který bude možné navzájem propojovat. Mít tedy připravené části, které budou v některých místech opticky stejné, a proto bude možné mezi nimi navzájem přeskočit, aniž by si to uživatel uvědomil. 2. Dále je potřeba, aby bylo možné na základě optických vjemů určit přesně snímky, kterými budou jednotlivé video části navzájem propojeny. První podmínku lze splnit pouze při natáčení, při zpracovávání výsledného videa ji již nijak zásadně ovlivnit nelze. Na druhou podmínku se naopak musíme zaměřit při konečném zpracovávání materiálu. Její úspěšnost lze ovlivnit případnou modifikací natočených snímků, nicméně pouze při splněné první podmínce. Fáze natáčení Forma tvorby videoobsahu použitelného pro interaktivní zobrazení se v zásadě nebude lišit od současné. Vzhledem k nutnosti u současných filmů mít před započetím samotného natáčení velice propracovaný a jasný scénář, včetně detailů jako nájezdy kamer a směru pohledu na scénu, neměl by být problém zapracovat také jasné definice míst, kde se scénář bude větvit. Právě ale kvůli možnsti větvení a následného možného opětovného sloučení budou kladeny větší nároky na zajištění celistvosti scén a jejich provázanost. Bude také nutné počítat s vyššími nároky na uskladnění video materiálu. Ty budou lineárně vzrůstat s jeho délkou. Fáze propojování Pro připravené video v jednotlivých stopách je důležité vymyslet systém zapisování informací o odbočení, který bude intuitivní na ovládání a jednoduchý pro integraci do současných nástrojů zpracovávajících video materiál. Obojí je proveditelné a náročnost těchto úkonů by měla být v rámci znalostí, které potřebuje současný uživatel programů pro manipulaci s videem. Bylo rozhodnuto, že systém začne přehráváním stopy, která bude v informacích o odbočení uvedena jako první. Díky tomuto rozhodnutí a v souvislosti s požadavkem na ukládání dat v rámci standardu MPEG-4, lze například do fyzicky první stopy v kontejneru (kterou také začne naprostá většina video přehrávačů přehrávat jako první) umístit informaci o speciálním interaktivním obsahu a jeho využití. A přehrávačem uzpůsobeným pro přehrávání interaktivního videa pak začít přehrávat jinou stopu, která bude uvedena v informacích o odbočení. Takto lze efektivně upozornit uživatele, který nemá potřebný software pro přehrávání a přitom neobtěžovat uživatele, který tyto požadavky splňuje.
Obě základní podmínky lze splnit. Obtížnost vytváření interaktivního videa by se neměla nijak zásadně lišit od současného způsobu tvorby videomateriálu. Jediný problém by tak mohly představovat zvýšené nároky na potřebné místo pro ukládání videa.
2.3
Kontejner
Kontejner je všeobecný název pro soubor nesoucí v sobě multimediální stopy. Těm zajišťuje vzájemnou časovou synchronizaci, nese v sobě informaci o jaké stopy se jedná (obrazová, zvuková,
KAPITOLA 2. ANALÝZA A NÁVRH ŘEŠENÍ
7
titulky, případně se může jednat o nějaké speciální stopy) a jakým způsobem byly zakódovány. Některé kontejnery také mohou nést dodatečné informace jako třeba obrázky obalů, kapitoly, menu. Kontejnerů existuje mnoho druhů, zde jsou příklady těch nejpoužívanějších: • AVI - Zkratka pojmu Audio/Video Interlave, vyvinula jej firma Microsoft. Pro moderní kodeky poměrně nevhodný kontejner, nicméně stále široce používaný. • MPEG - Celým názvem Motion Picture Experts Group, ISO standard. Kontejner používaný především v DVD discích. Je vhodný také pro streamování po internetu. Vnitřně jde o prokládání obrazu a zvuku tak, že vytvoří jeden stream. • Matroška - Open source kontejner, jeho vnitřní struktura je založena na binární formě populárního jazyka XML. Je orientován na širokou rozšiřitelnost. Ve streamech umožňuje nést téměř jakákoli data. • MP4 - Je součástí ISO standardu MPEG-4. Moderní kontejner, který umožňuje kromě více obrazových i zvukových stop nést další data. Jako třeba titulky nebo 3D objekty. Je uzpůsobený i pro streamování po internetu. Nakonec, jako kontejner obalující veškeré stopy a dodatečné informace byl vybrán MP4. Tento formát podporuje uložení více stop videa do jednoho souboru. [11] Jeho popis můžeme nalézt v části 14 specifikace formátu MPEG-4. [12] Je také vhodný pro streamování obsahu přes internet, k čemuž možná budeme v budoucnu směřovat.
2.4
Informace o odbočení
Pro požadovanou interaktivitu, která by uživateli umožnila zvolit si (v předem definovaných místech) následující děj, bylo nutno vybrat a definovat způsob, jakým se tyto informace budou přenášet a jaký budou mít formát. O tom pojednává tato kapitola. 2.4.1
Uložení informací
Nejprve bylo potřeba určit způsob přenášení těchto informací. Před touto volbou je třeba si ujasnit, jaké budou kladeny požadavky na výsledný přehrávač. Zda budeme potřebovat schopnost dynamicky měnit tyto informace během přehrávání a zda jsme omezeni množstvím souborů, které budeme k přehrávání potřebovat (tedy jestli informace o odbočení musí být spolu s multimediálními daty v kontejneru nebo jestli mohou být v externím souboru). Vzhledem k tomu, že současný návrh předpokládá nasazení ve formě aplikace na osobním počítači, nepředpokládáme změnu videoobsahu během přehrávání. Ani nutnost měnit dynamicky informace o odbočování tak není nutná. Ta by byla přínosná v případě použítí přehrávače formou server-klient. Bylo by pak možné předávat klientu pouze aktuální obrazová data s momentální možností odbočení. Nejsme ani omezeni počtem použitých souborů. Přestože by bylo vhodnější mít vše v jednom souboru. Nemohlo by pak dojít k situaci, kdy by se omylem přenesl jen soubor s videem. Ten by byl následně nepoužitelný, protože bychom neměli informaci o možnostech odbočení.
8
KAPITOLA 2. ANALÝZA A NÁVRH ŘEŠENÍ
Obrázek 2.3: Nákres přehrávání obsahu formou server - klient
Existují tedy v zásadě tři varianty uložení informací: • Zvláštní stopa v kontejneru, která ponese jen ony informace. Byla by možnost informace aktualizovat v průběhu přehrávání, případně je posílat jednou za čas celé znova. Na příklad, kvůli streamovanému přehrávání. • Informace budou uloženy taktéž přímo v souboru s videem, ale ne ve formě samostatné stopy. Budou jednorázově přibaleny na začátku kontejneru. • Informace o odbočení budou v externím souboru. Z těchto variant by byla nejvhodnější první, tedy infomrace ve formě samostatné stopy. Hlavně kvůli budoucí jednoduché rozšiřitelnosti o další funkce a připravenosti na streamované vysílání. Bohužel je ale tato varianta také nejvíce náročná, proto byla zvolena vaianta třetí, tedy externí soubor. Je nejjednodušší na implementaci a nejsnadnější na pozdější editaci hodnot při experimentování. Bylo také rozhodnuto, že tento formát bude mít pevně daný název. Musí se jmenovat stejně, jako načítaný soubor s videem a navíc mít příponu .sw. 2.4.2
Formát souboru
Nejprve proběhlo zvolení základního rozdělení, zda formát binární nebo textový. Byl vybrán textový z důvodu umístění v externím souboru a jeho následné jednoduché editace uživatelem. Samotná informace o možnosti odbočnení se skládá z posloupnosti sedmi čísel (mohou být oddělena mezerou, tabulátorem nebo odřádkováním). A to v následujícím uspořádání: 1. číslo prvního streamu 2. začátek sekce v prním streamu 3. konec sekce v prvním streamu 4. číslo druhého streamu 5. začátek sekce v druhém streamu 6. konec sekce v druhém streamu
KAPITOLA 2. ANALÝZA A NÁVRH ŘEŠENÍ
9
7. určení strany na kterou se bude odbočovat (1 pro levou, 2 pro pravou) Číslo streamu je absolutní pořadí streamu v kontejneru (včetně všech streamů ostatních typů). Začátky a konce sekcí označují čísla snímků. Sekce je pak oblast, ve které je v programu funkce odbočení aktivní (program přijímá a zpracovává požadavky na konkrétní odbočení). Zde je vhodné přpomenout, že právě v první posloupnosti je první číslo určující pro začátek přehrávání. Přehrávání nemusí tedy nutně začínat na prvním streamu. Formát je tímto způsobem libovolně rozšiřitelný. Záleží jen na parseru, jakým způsobem bude soubor zpracovávat. 2.4.3
Provedení odbočení
Před určením, jakým způsobem bude samotné odbočení probíhat, je vhodné zamyslet se nad tím, jak dávat uživateli najevo, že má možnost odbočit. Tuto informaci je možné signalizovat několika způsoby. • Znamením přímo ve videu. Například šipkou, ukazující směr nebo značkou v rohu přehrávaného videa. Způsobů grafického znázornění je jistě mnoho. • Externím způsobem. Zvukovým znamením, případně textovým výpisem. • Nedávat žádné znamení. Ač se to nemusí na první pohled zdát, nejlepší by byla třetí možnost, tedy nedávat žádné znamení. Při „správněÿ připraveném interaktivním videu by měl být uživatel sám schopen poznat kde možnost odbočení má a kde ne (například pokud přijde na křižovatku, logicky má předpokládat, že si může vybrat, kterým směrem bude pokračovat dále). Není žádoucí uživateli přerušovat dojem kontinuálního videa nadbytečnými volbami. Na druhou stranu je dobré alespoň základním způsobem uživatele informovat. Použijeme proto kombinaci s textovým výpisem mimo video. Samotné provedení odbočení je potřeba chápat z několika rovin. • První věcí, kterou je při odbočení třeba udělat, je změna čteného streamu ze souboru. • Dále je potřeba přečtená data správně dekódovat. Každý stream si totiž nese svou informaci, jak byl zakódován. • Po těchto věcech je potřeba zajistit, že následné čtení snímků z nového streamu bude pokračovat na místě, které známe z informací k odbočení.
Obrázek 2.4: Jednoduché schéma vnitřní struktury kontejneru Tento nákres představuje fyzickou strukturu kontejneru, jednotlivé streamy jsou takto po částech prokládány. Při čtení tedy stačí vyměnit aktuální čtený stream (ostatní se přeskakují). Získávání jednotlivých snímků z proudu dat probíhá pomocí dekodéru. Ten je vhodné použít pro všechny video streamy stejný, kvůli menší paměťové náročnosti i kvůli transparentnímu a přehlednému sestavování video souboru. Zároveň je nutné, aby všechny streamy měly stejné rozlišení a stejnou snímkovou frekvenci, pokud by toto nesplňovaly nebylo by možné správně určit rychlost přehrávání.
10
KAPITOLA 2. ANALÝZA A NÁVRH ŘEŠENÍ
Poslední věcí, kterou je potřeba zajistit, je správná návaznost jednotlivých snímků po odbočení. Kterým snímkem navazuje nový stream zjistíme z informací ke konkrétnímu odbočení. A protože není jisté (jak je například vidět z obrázku 2.2), že nový stream bude správně navazovat na aktuální pozici tam, kde starý zkončil, je potřeba se v novém streamu přesunout na požadovaný snímek. Z toho plyne i libovolná délka jednotlivých streamů, na požadovaný úsek se můžeme vždy přesunout. Z těchto informací tedy vyplývá několik následujících poznatků: • oba streamy musí mít stejný kodek • oba streamy musí mít stejné rozlišení • oba streamy musí mít stejnou frekvenci snímků • oba streamy nemusí být stejně dlouhé Se splněním těchto požadavků je nutno počítat již při začátku natáčení materiálu. Protože ale budeme pravděpodobně vždy jednotlivé videostopy natáčet stejnými přístroji, požadavky na rozlišení i frekvenci snímků by měly být automaticky splněny. Požadavek stejného kodeku také žádný problém nepředstavuje.
2.5
Vstup od uživatele
Pro následující tři kapitoly je důležité vědět, jakým způsobem budeme získávat podněty od uživatele, jak se chce ve videu pohybovat. Teoreticky lze jako vstupní zařízení zvolit jakékoli, které je schopné na uživatelovy příkazy dostatečně rychle reagovat. Pro demonstrační účely byla zvolena klávesnice a gamepad. Zásadním prvkem, který bude velkou měrou určovat míru interakce s uživatelem, je rychlost reakce na vstupy uživatele. Je velice důležité, aby měl pocit, že přehrávané video skutečně reaguje na jeho podněty.
2.6
Přehrávání pozpátku
Přehrávání pozpátku je další požadavek uvedený v zadání. Protože pro splnění této podmínky nelze místo čtení jednoho snímku vpřed, číst jednoduše jeden snímek vzad, je potřeba přiblížit způsob zakódování jednotlivých snímků ve streamu. Číst jeden snímek vzad totiž ve video streamu obecně nelze. Přípustné jsou pouze pohyby vpřed a skok (i dozadu). 2.6.1
Zakódování snímků
Ve videu standardu MPEG-4 existuje několik druhů snímků: • I frame - klíčový snímek, může existovat samostatně, obsahuje celou informaci o obraze • B frame - tento snímek vychází z předcházejícího a následujícího snímku • P frame - snímek, který vychází pouze z předcházejícího snímku • D frame - tento typ snímku se nepoužívá Snímky jsou vždy ve videu zakódovány jako posloupnost začínající klíčovým snímkem a za ním následují snímky odvozené od něj. Je tedy jasné, že pokud chceme zobrazit snímek typu B nebo P, musíme před ním dekódovat klíčový snímek, který jako jediný můžeme zobrazit bez informací z okolních snímků. A tento poznatek je důležitý při našem pohybu vzad. Pokud totiž snímek za námi je typu B nebo P a my jej potřebujeme zobrazit, jediný způsob jak toho dosáhnout, je nejprve se přesunout a dekódovat snímek typu I, na který ukazují.
KAPITOLA 2. ANALÝZA A NÁVRH ŘEŠENÍ 2.6.2
11
Způsob načítání snímků
Protože, jak bylo řečeno v kapitole 2.6.1, nelze načítat snímky pozpátku pouhou změnou směru, tedy místo o jeden snímek vpřed číst o jeden snímek zpět, bylo nutno vymyslet jiný způsob. Jako jediná možná a zároveň použitelná (např. uchovávat v paměti programu nekomprimované snímky celého videa není technicky možné) varianta se ukázala následující:
Obrázek 2.5: Načítání snímků pro přehrávání pozpátku Jak je z obrázku vidět, při přehrávání pozpátku, pokud nemáme další snímky v zásobě, nemůžeme předpokládat, že předcházející snímek je klíčový. Proto je potřeba se přesunout na nejbližší klíčový snímek a od něj doplnit snímky až k aktuálnímu místu. Tímto způsobem si tedy zajistíme libovolný pohyb vpřed i vzad. Ale jedním z velkých problémů tohoto návrhu se ukázala časová náročnost této operace. Pokud jsme aktuálně na posledním snímku a potřebujeme přehrát snímek předcházející, není technicky možné během jednoho časového intervalu mezi dvěma snímky načíst a dekódovat větší množství snímků. Je proto potřeba začít ony snímky načítat s jistým předstihem. Na základě experimentování s pokusným videem se jako naprosto dostatečná ukázala hodnota 50-100 snímků před koncem fronty.
2.7
Snímky za sekundu
Následovalo rozhodnutí, zda přehrávat konstantní počet snímků za sekundu. Např. 25, nezávisle na aktuálním dění (zda video stojí, či uživatel vydal pokyn k pohybu). Nebo mít variabilní počet snímků za sekundu, podle rychlosti přehrávání odvozené od původní frekvence snímků. Oba návrhy by byly pro náš účel použitelné, nicméně konstatní počet snímků za sekundu je více vhodný pro streamování po síti. Pro naše potřeby se mnohem více hodí varianta variabilního snímkování. Uživatel přehrávání založené na konstantním počtu snímků nepotřebuje a ten by pak pouze zbytečně zatěžoval výpočetní jednotky. Proto byla vybrána varianta proměnlivého snímkování.
2.8
Změna rychlosti
Při přehrávání je také důležitá možnost plynule měnit rychlost přehrávání. Tato vlastnost uživateli mnohem lépe zprostředkuje zážitek a dá mu skutečnou možnost ovládat přehrávaný obsah. Podstatná je právě ona plynulost. Pokud například uživatel dá povel z klidu k chůzi, přehrávaný obsah se plynule rozeběhne. Nebude se tedy jednat o prosté dva stavy stůj a jeď. V souvisosti s rozhodnutím v předchozí kapitole, tedy mít při přehrávání proměnlivou frekvenci snímků, stačí na základě vstupů od uživatele měnit dobu, za kterou bude zobrazen další snímek. Je to tedy pouze záležitost reprezentace dat uživateli, na vnitřní strukturu tato funkce mít vliv nebude. Je ale důležité uvědomit si, že pravděpodobně připravené video není stavěné na pomalé přehrávání. Při natáčení mělo nastavené určitý počet snímků za sekundu a pokud je snížíme, uživatel
12
KAPITOLA 2. ANALÝZA A NÁVRH ŘEŠENÍ
velmi snadno pozná, že se video „trháÿ. Snímek bude zorazen příliš dlouho a rozdíl mezi aktuálním a následujícím snímkem bude opticky příliš velký, takže uživatel začne místo plynulého videa vnímat obsah jako sled statických obrázků. Tomu lze zabránit interpolací mezi dvěma snímky a zobrazením tohoto mezisnímku v průběhu čekání na další snímek.
KAPITOLA 3. REALIZACE
13
3 Realizace V této kapitole je popsána konstrukce přehrávače interaktivního videa navrhovaného v kapitole 2.
3.1 3.1.1
Úvod Vývojové prostředky
Program byl implementován v jazyce C++, ten asi netřeba blíže představovat. Dále bylo využito knihoven z projektu ffmpeg a pro výstup na obrazovku knihoven OpenGL. Projekt ffmpeg se zabývá, mimo jiné, dekódováním obrazu z multimediálních souborů. Díky němu se pracovalo už s hotovými snímky z videa. Prostředí OpenGL pak bylo využito pro výstup, ať už do okna na obrazovce či na celou obrazovku. Hlavně z důvodu využití vláken pthread a použití funkcí Xserveru je program dostupný pouze pod operačním systémem Linux. 3.1.2
Použité programy
• KDevelop - vývojové prostředí, mimo jiné i pro C++ • Valgrind - utilita virtualizující běh procesoru, díky ní je možné velice snadno nacházet a ladit úniky paměti v programech 3.1.3
Knihovna ffmpeg
Knihovny projektu ffmpeg poskytují framework pro práci s multimediálními soubory. Programátor se nemusí starat přímo o práci se samotnými pakety a dekódovat je, potřebné funkce mu poskytuje tato knihovna.[1] [2] Dvě nejpoužívanější funkce: • int av read frame(AVFormatContext *s, AVPacket *pkt) Funkce, která, pro video, přečte jeden snímek. Ten najdeme ve struktuře AVPacket. Dále se pak musí dekódovat pomocí funkce int avcodec decode video(AVCodecContext *avctx, AVFrame *picture, int *frameFinished, uint8 t *buf, int buf size). Z ní už programátor dostane snímek přímo ve zvoleném rastrovém fromátu. Např. v RGB (tedy dvourozměrné pole hodnot, kde pro každý pixel existují tři hodnoty a každá zastupuje jednu barvu ze schématu RGB). • int av seek frame(AVFormatContext *s, int stream index, int64 t timestamp, int flags) Funkce používaná pro pohyb ve streamu. Při používání funkce av read frame() se pohybujeme konstantně o jeden snímek dopředu, když se však potřebujeme posunout dozadu nebo dopředu o větší počet snímků, použijeme právě této funkce. Pokud nezadáme jinak, standardně se skáče pouze na klíčové snímky. Funkce podle proměnné flags najde nejbližší následující nebo předcházející klíčový snímek od požadovaného cíle.
14
3.2 3.2.1
KAPITOLA 3. REALIZACE
Vlákna Obecně
Celá implementace je řešena pomocí dvou vláken. Toto rozhodnutí bylo nutné, protože přehrávání jednotlivých snímků uživateli je silně časově závislé. Bylo proto nutno zajistit plynulé přehrávání před uživatelem a současně nezávisle na pauzách mezi jednotlivými snímky aktualizovat a udržovat frontu snímků. Jedno vlákno slouží k načítání snímků, jejich řazení, odbočování ve videostopách, zpracovávání požadavků na změnu stavu a pod. Dále v textu je označováno jako „Workerÿ. Druhé vlákno je používáno pro zobrazování jednotlivých snímků a zpracovávání uživatelských vstupů. Dále v textu je označováno jako „Displayÿ. Následující obrázek naznačuje spolupráci obou vláken a jejich vstupů.
Obrázek 3.1: Diagram funkce programu a vláken
KAPITOLA 3. REALIZACE
15
Po spuštění programu je vytvořen proces (vlákno Display), to dále vytvoří potřebné struktury a s nimi i vlákno Worker. Komunikace mezi vlákny probíhá oběma směry. Vlákno Display si od vlákna Worker přebírá ukazatele na čistá data jednotlivých snímků (v RGB) a posouvá ukazatel fronty na aktuálně přehrávaný snímek. Zároveň vznáší požadavky k vláknu Worker, to provádí pomocí funkce void VideoReader::demand(int co, int prom), viz. 3.3.1. 3.2.2
Sdílené prostředky
Protože vlákna navzájem používají sdílené prostředky, bylo nutné kvůli synchronizaci použít tzv. mutexy. Tedy proměnné, které zajistí v nebezpečných sekcích vždy přístup pouze jednoho vlákna. Druhé v případě nutnosti zablokují. Tyto mutexy byly použity tři: • mread - mutex pro práci s framebufferem (viz. kapitola 3.3.2.1) • mflag - mutex pro práci s příznaky (proměnná flag, vysvětlena v kapitole 3.3.1) • mctx - mutex pro práci s kontextem jednotlivých stop (viz. kapitola 3.3.4.2)
16
KAPITOLA 3. REALIZACE
3.3
„Workerÿ vlákno
Celé vlákno pracuje pouze nad třídou VideoReader, v jejímž konstruktoru je vlastně samotné vytvořeno. Zároveň při zavolání destruktoru třídy VideoReader je toto vlákno zničeno. Pro vlákno Display je tedy používání třídy VideoReader velice transparentní a pouze si z ní „vybíráÿ nové snímky, nestará se o jejich načtení. 3.3.1
Požadavky ve vláknu Worker
Požadavky slouží ke komunikaci obou vláken, ale pouze směrem od vlákna Display ke vláknu Worker. Pro požadavky, které vlákno zpracovává, byla vytvořena velice jednoduchá struktura fronty. struct Priznak { Priznak *next; int co; int jak; Priznak(); }; Díky uchovávání požadavků ve frontě, je zaručeno jejich zpracovnání přesně v pořadí, ve kterém přišly. Také právě díky implementaci fronty není množství požadavků v jeden okamžik omezeno. Nemůže se tedy stát, že by nějaké požadavky byly zapomenuty. 3.3.1.1
Zařazení požadavku
Požadavky, které se objeví, se zařadí do fronty pomocí jednoduché procedury. Ta je ošetřena pomocí výše zmiňovaného mutexu mflag. Je to nutné, protože existuje možnost, že by si vlákna navzájem přepsala přidávaný požadavek. Případně, že by se vlákno Display snažilo přidat požadavek do struktury na místo, které právě vlákno Worker smazalo. Tím by došlo k nekonzistenci, úniku alokované paměti a zároveň ztrátě přidávaného požadavku. void VideoReader::demand(int co, int prom) { pthread_mutex_lock(&mflag); Priznak *tmp=flag; if (flag == NULL) { flag = new Priznak; tmp = flag; } else { while (tmp->next != NULL) { tmp=tmp->next; } tmp->next = new Priznak; tmp=tmp->next; } tmp->co = co; tmp->jak = prom; pthread_mutex_unlock(&mflag); return ; }
KAPITOLA 3. REALIZACE
17
Proměnná „int coÿ nám určuje o jaký typ požadavku se jedná a proměnná „int promÿ specifikuje tento typ požadavku blíže. Z vypsaného kódu je vidět, že při přidávání nejprve najdeme konec fronty a za něj pak přidáme nový požadavek. Jednotlivé struktury se vytvářejí dynamicky, nesmíme proto zapomenout je také po použití sami mazat. 3.3.1.2
Zpracování požadavků
Zpracování požadavků obsluhuje switch ve funkci void VideoRreader::buffercare(). Je také (stejně jako zařazení požadavku) celý obalen v mutexu mflag (právě proto, že tuto funkci obsluhuje vlákno Worker, kdežto funkci VideoReader::demand většinou vlákno Display) a zpracovává tyto požadavky: • ZRUS_ODBOCENI - podle toho, v jaké fázi se přehrávač nachází, ruší připravené proměnné a připravený buffer na odbočení (blíže o tomto pojednává kapitola 3.3.4) • SKOK - momentálně se v programu nepoužívá, protože jeho funkce není potřeba, nicméně zůstává stále funkční a proto je možné ho kdykoliv znovu zapojit do programu • ODBOCIT - kontroluje, zda je odbočení možné a případně nastavuje potřebné proměnné a struktury (blíže v kapitole 3.3.4) • RESET - aktuálně taktéž nepřístupná funkce, ale protože původně bylo její zařazení v plánu a je možné, že v budoucnu se použije, je takto připravena 3.3.2
FrameBuffer
FrameBuffer je struktutra uchovávající jeden snímek z přehrávaného videa. Tyto struktury se pak řadí do obousměrného seznamu. To je zvláště vhodné kvůli požadovanému přehrávání videa popředu i pozpátku. struct FrameBuffer { AVFrame *pFrameRGB; uint8_t *pixelbuf; FrameBuffer *prev; FrameBuffer *next; int id; /*cislo snimku*/ int stream; /*cislo streamu ze ktereho snimek je*/ int can_delete; /*boolean, zda se snimek muze smazat (zda ho prave nezpracovava Display vlakno)*/ FrameBuffer(); ~FrameBuffer(); }; Proměnné id a stream jsou nutné kvůli jednoznačné identifikaci snímku ve videu. Většinou stačí pouze informace o pořadí snímku (id), ale v průběhu skoku a při jeho případného rušení je potřeba vědět, který snímek je z plánovaného skoku, a proto je potřeba jej zrušit, a který je třeba ponechat. Buffer je v programu implementován s limity na obě strany. Ty určují, kolik snímků bude vlákno přednačítat. Pracuje se s určitou hysterezí, tedy např. vlákno bude přednačítat snímky do maxima 50 a pak, až počet přednačtených snímků klesne pod 20, znovu jejich počet doplní do 50-ti. Vše je znázorněno na následujícím obrázku.
18
KAPITOLA 3. REALIZACE
Obrázek 3.2: Nákres funkce bufferu a jeho zaplnění Tento nákres ukazuje funkci bufferu a jeho nastavení. Buffer si od aktuálního místa pamatuje vždy minimální definovaný počet snímků směrem vpřed i vzad. To je důležité zvláště při přehrávání videa, které nemá každý snímek jako klíčový, a proto je potřeba při pohybu změrem zpět mít dostatečný čas na načtení většího bloku dat (až 200 snímků najednou). 3.3.2.1
Práce s mutexem
Veškeré přístupy do fronty se snímky musí být obaleny mutexem (k tomuto je určen mutex mread). Je to kvůli současnému přístupu vlákna Worker, kvůli přidávání a mazání snímků ve frontě a zároveň přístupu vlákna Display, naopak kvůli vybírání snímků a jejich reprezentaci. 3.3.3
Přehrávání pozpátku
S předpřipraveným obousměrným bufferem na snímky bylo potřeba pouze dopsat funkci pro načítání. Dle analýzy v 2.6 se muselo nejdříve ve videu skočit od požadovaného místa na první klíčový snímek před ním. Poté vytvořit dočasnou frontu, do které byly ukládány načtené snímky, a nakonec tuto dočasnou frontu připojit k té hlavní. 3.3.4
Odbočení
Pro realizování funkce odbočení (tedy plynulé změny streamu) bylo potřeba vytvořit několik struktur. Strukturu uchovávající informace, odkud kam se dá odbočovat. Ta se vytváří v konstruktoru třídy, při zapnutí programu. Po zbytek přehrávání se tedy nemění. Nicméně formát je navržen tak, aby případné změny, podle jiného návrhu, byly možné. struct Switch { Switch int
*next; stream1, stream2;
19
KAPITOLA 3. REALIZACE
int int int Switch();
start1, start2; stop1, stop2; kam;
}; Strukturu uchovavající informace o kontextu jednotlivých stop. Vytváří se pro každý stream zvlášť. Ke kterému streamu patří pak poznáme, podle proměnné id. Není tedy nutné, aby byly nějak seřazeny. struct SwitchCtx { SwitchCtx *next; int id; AVCodecContext *pCodecCtx; SwitchCtx(); ~SwitchCtx(); }; A pomocnou strukturu k samotnému provádění odbočení. Ta pouze propojuje dva snímky, na kterých má program přeskočit na nový stream. struct sSkok { int source_frame; int dest_frame; int source_stream; int dest_stream; }; Informace o možnostech odbočení se nachází v externím souboru. Ten musí být pojmenován stejně jako otevíraný multimediální soubor a má příponu .sw. Kromě těchto struktur byla potřeba stavová proměnná state, která vlákno informovala o stavu odbočení.
Obrázek 3.3: Automat odbočení
20
KAPITOLA 3. REALIZACE
State 0 Základní stav, v případě příchodu požadavku na odbočení se zkontroluje, zda je v této části videa možný. Pokud ano, nastaví informace o skoku do struktury sSkok (viz. výše) a přejde do stavu 1. Ve všech ostatních stavech se požadavek na odbočení ignoruje. State 1 V tomto stavu vlákno při načítání nových snímků kontroluje, zda nenarazilo na tzv. „skokový snímekÿ, tedy poslední snímek v daném streamu od kterého se má odbočit. Pokud na něj vlákno narazí, nastaví nový stream, ze kterého se budou načítat snímky a v onom novém streamu najde požadovaný počáteční snímek. Pak přejde do stavu 2. State 2 Zde se pouze čeká, na samotné zobrazení prvního snímku z nového streamu uživatelem, pak se přechází do stavu 3. Tento stav je důležitý kvůli případnému rušení skoku. Musí se totiž v tom případě vracet zpátky stopa, ze které se budou načítat snímky a musí se zpátky nastavit následující snímek. State 3 Tzv. „uklízecí stavÿ. V tomto stavu je již odbočení dokončeno, načítá se z nové stopy i snímky z ní jsou již zobrazovány uživateli. Zde se proto zruší zbytek snímků z předcházející stopy a stav se nastaví na základní, tedy 0. 3.3.4.1
Zrušení skoku
Způsob jak vyvolat zrušení skoku je zatím pouze jeden. A tím je někdy mezi stavy 1 a 2 změnit směr přehrávání. Poté je nastávající skok zrušen a video dále pokračuje (i po opětovné změně směru) jako bez požadavku na odbočení. Ten je ale samozřejmě možné opětovně vyvolat. 3.3.4.2
Práce s mutexem
Pro odbočení se používá mutex mctx. Nutný je proto, že při odbočování ze stavu 2 do stavu 3 přechází vlákno Display. O zbytek odbočení se stará vlákno Worker. Je tedy třeba zajistit, aby si vlákna state navzájem nepřepsala.
21
KAPITOLA 3. REALIZACE
3.4
„Displayÿ vlákno
Toto vlákno obstarává komunikaci mezi daty a uživatelem. Zajišťuje jak vstupy od uživatele, tak výstupy k uživateli. Samo o sobě data nevytváří, pouze je zprostředkovává, protože je u něj kladen největší důraz na časovou přesnost. Nesmí být proto moc zatíženo. 3.4.1
Ovládání
Program se dá ovládat dvěma způsoby. Klávesnicí nebo gamepadem. Vlákno samo si při startu programu pokusí připojit gamepad, který očekává na vstupu /dev/input/js0. Pokud se mu to nepovede, samo přejde na ovládání klávesnicí. 3.4.1.1
Klávesnice Klávesa šipka nahoru šipka dolů šipka doleva šipka doprava mezerník esc
Funkce chůze dopředu chůze pozpátku požadavek na odbočení doleva požadavek na odbočení doprava pauza ukončení programu
Tabulka 3.1: Ovládání pomocí klávesnice Zde je naznačeno ovládání klávesnicí. Při stisku šipek nahoru nebo dolů se simuluje postupný nárůst rychlosti přehrávání až do maxima 100%. Naopak pokud není stisknutá žádná klávesa, pak se rychlost přehrávání postupně snižuje až na 0 (přehrávání stojí). Viz. následující ukázka kódu. if (up) { rychlost<0 ? rychlost+=2*ZRYCHLENI : rychlost+=ZRYCHLENI; up=0; } else if (down) { rychlost>0 ? rychlost-=2*ZRYCHLENI : rychlost-=ZRYCHLENI; down=0; } else { if (rychlost > 0) { rychlost -= ZRYCHLENI; } else if (rychlost < 0) { rychlost += ZRYCHLENI; } if (((rychlost<0) && (rychlost>-ZRYCHLENI)) || ((rychlost>0) && (rychlost
22 3.4.1.2
KAPITOLA 3. REALIZACE Gamepad Klávesa kolébka nahoru kolébka dolu kolébka doleva kolébka doprava tlačítko 0 tlačítko 1
Funkce chůze dopředu chůze pozpátku požadavek na odbočení doleva požadavek na odbočení doprava pauza ukončení programu
Tabulka 3.2: Ovládání pomocí gamepadu Ovládání gamepadem je pro uživatele mnohem intuitivnější a působí přirozeněji je proto preferováno. Funkce pro obsluhu gamepadu je velmi podobné té pro klávesnici: if (joy.readed == sizeof(struct js_event)) { switch (( joy.js.type & 0x03 )) { case JS_EVENT_BUTTON: switch ((int)joy.js.number) { case 0: pause = !pause; break; case 1: run = false; break; } break; case JS_EVENT_AXIS: switch ((int)joy.js.number) { case JOY_POJEZD: rychlost = joy.js.value + JOY_CALIB; rychlost /= JOY_DIV; break; case JOY_ODBOC: if (joy.js.value == JOY_MAX) { r->demand(ODBOCIT, PRAVA); } else if (joy.js.value == JOY_MIN) { r->demand(ODBOCIT, LEVA); } break; } break; } } Proměnná rychlost se však trochu odlišněji počítá. Gamepad vrací jako hodnotu typ integer, který může mít různou velikost. Simulace plynulého pohybu proto jako u klávesnice není nutná. Získáme ji už z ovladače.
KAPITOLA 3. REALIZACE 3.4.2 3.4.2.1
23
Zobrazení Snímky za sekundu
Podle analýzy v kapitole 2.7 bylo vybráno proměnlivé snímkování. To se vypočítává z údaje o rychlosti, který představuje relativní rychlost vůči originálu. Toto úzce souvisí s možností měnit plynule rychlost videa během přehrávání. Aktuální stav rychlosti přehrávání obsahu je v proměnné rychlost a ta se mění na základě vstupů od uživatele. Algoritmy výpočtu rychlosti přehrávání v závislosti na druhu ovládání (klávesnicí nebo gamepadem) jsou představeny v kapitolách (3.4.1.1 a 3.4.1.2). Příklady stavů proměnné rychlost: • rychlost = 0, video stojí • rychlost = 1, video se přehrává rychlostí stejnou jako originál • rychlost = -1, video se přehrává stejnou rychlostí, ale pozpátku • rychlost = 0.5, video se přehrává poloviční rychlostí vůči originálu Práce s časem a čekáním na další zobrazení snímku pak probíhá takto: t3=tim.tv_sec*1000000+tim.tv_usec; //aktualizace času t2 = t3-t4; if (rychlost) delay += t2; //čas po který se nezobrazil snímek t4=t3; t1 = rychlost ? abs(int(reader1->getFrameDelay() / rychlost)) : 0; //modifikace snímkové frekvence if (delay > t1) { if ((!pause) && (rychlost!=0)) { if (rychlost > 0) { ret = reader1->getFrame(1); //přehrávání dopředu } else if (rychlost < 0) { ret = reader1->getFrame(-1); //přehrávání pozpátku } else { ret = reader1->getFrame(0); //přehrávání stojí } if (ret == NULL) { cerr << "frame not ready !" << endl; } else { okno1->setFrame(ret); okno1->drawGLScene(0); //zobrazení snímku reader1->canDelete(); } } if (t1) delay %= t1; //odečet čekání na právě zobrazený snímek spi = int(t1-delay-t2); //předpověď čekání na další aktivitu if (spi>MAXDELAY) spi=MAXDELAY; //korekce čekání, program // musí reagovat na vstupy if (spi>0) usleep(spi); Komentáře snad objasňují funkci dostatečně jasně. V proměnné t1 se nachází hodnota času, která přestavuje vypočtený interval podle aktuální rychlosti a snímkové frekvence videa. Ta se pak porovnává se skutečnou dobou čekání a podle jeho výsledku se funkce dále chová.
24 3.4.2.2
KAPITOLA 3. REALIZACE Vykreslování
Pro vykreslování se používá knihovny OpenGL. Díky možné hardwarové akceleraci je zobrazování snímků mnohem méně náročné na čas procesoru. Zajímavá je funkce, která bude pravděpodobně využitelná v budoucnu. Jedná se o, v případě příliš pomalého přehrávání, doplňování snímků do obrazu. Funkce vezme pole hodnot (pole bodů, kdy každý bod má tři hodnoty, barevné složky RGB) a překopíruje jej, přičemž ke každému pixelu vytvoří čtyři hodnoty (tři stávající) a jako čtvrtou doplní informaci o průhlednosti (RGBA): if (alpha!=0) { uint8_t *buff=(uint8_t *)malloc(4*movieWidth*movieHeight*sizeof(uint8_t)); for (int i=0; i<movieWidth*movieHeight; i++) { buff[i*4] = frame[i*3]; buff[i*4+1] = frame[i*3+1]; buff[i*4+2] = frame[i*3+2]; buff[i*4+3] = alpha; } } Ale právě vzhledem k hrubému překopírovávání dat bude nanejvýš vhodné v budoucnu využití této funkce přehodnotit viz. kapitola 4.2.
KAPITOLA 4. DISKUZE
25
4 Diskuze 4.1
Splněné požadavky
Program velmi dobře splnil očekávání v oblasti poskytnutí větší interaktivity uživateli. A to především díky následujícím vlastnostem: • změna rychlosti přehrávání - možnost plynule měnit rychlost dává pocit skutečného ovládání (například možnost zvolit rychlost „chůzeÿ, plynule se „rozejítÿ a další.) • změna směru přehrávání - obzvláště se hodí v případě simulace jízdy autem, můžeme kromě jízdy dopředu i couvat • volba směru přehrávání - velmi důležitou vlastností je i volba odbočení. Díky absenci jakýchkoli menu při přehrávání, která by uživatele „vytrhlaÿ z prostředí přehrávaného obsahu, jsme se dostali mnohem blíže k ideálnímu interaktivnímu videu.
4.2
Co nebylo realizováno
Stereoskopie V původním záměru byla také schopnost přehrávače přehrávat vícekanálové video (například obraz pro každé oko zvlášť). Tato možnost ale v programu nakonec není. Kvůli jiným problémům s vyšší prioritou se na ni nedostalo. Nicméně program je na tuto funkčnost připraven. V případě čtení z více kanálů současně, se vytvoří také více tříd VideoReader, v každé této třídě se pak automaticky vytvoří vlákno Worker, které pracuje pouze v rámci své třídy a v rámci svého kanálu. Těchto vláken proto může běžet více současně (pro každý kanál jedno). Informace o odbočení Podle kapitoly 3.3.4 zjistíme, že informace o možnostech odbočení ve videu se ukládají do externího souboru, který má stejný název jako vstupní multimediální soubor a navíc příponu .sw. Původně ale byl úmysl tyto informace přenášet přímo v kontejneru. Ať už jako vnořený soubor na začátku kontejneru nebo, lépe, ve zvláštní datové stopě. Specifikace MPEG-4 tuto možnost podporuje. [10] Bohužel se na ní nedostalo.
4.3
Možné budoucí problémy
• Určitým problémem může být, že pro navržené a implementované řešení interaktivního videa bude uživatel potřebovat speciální přehrávač. Nicméně tento problém není možné rozumně vyřešit a softwarový přehrávač se jeví jako nejsnažší cesta. Samotný soubor s videoobsahem je ale plně validní podle standardu MPEG-4. • Díky nestandardní implementaci přehrávání obsahu s proměnným snímkováním může například vzniknout problém při komunikaci po síti, protože nepůjde o konstantní datový tok, ale proměnný. To je ale implementační záležitost, samotného návrhu metody přehrávání obsahu se tento problém netýká. • V případě přehrávání videa s vysokým rozlišením můžou být kladeny velké nároky na rychlost procesoru a velikost pamětí počítače. Ideální jsou pro tento účel dvoujádrové procesory, právě kvůli rozdělení problému na dvě vlákna.
26
4.4
KAPITOLA 4. DISKUZE
Možnosti rozšíření/vylepšení
Jedním z možných budoucích rozšířeních je implementace dopočítávání snímků při příliš pomalému pohybu, aby se zabránilo „trháníÿ obrazu. Díky tomu by šlo také dosáhnout konstantní frekvence snímků. Momentálně je nutné, aby v místě odbočení nový stream přesně navazoval. By bylo proto vhodné do programu přidat podporu pro aproximaci snímků při odbočování. Díky tomu by pak odbočení mohlo začít přímo při uživatelově podnětu a ne až na definovaném místě.
KAPITOLA 5. ZÁVĚR
27
5 Závěr Podle zadání se podařilo úspěšně vybrat formát a analyzovat možnosti přehrávání interaktivního videa. V implementační části se podařilo úspěšně zrealizovat požadovaný přehrávač navrhovaného interaktivního obsahu. Při srovnání se současnými způsoby přehrávání interaktivního videa zmíněnými v úvodu (viz. 1.2), můžeme konstatovat, že se podařilo navrhnout nový formát, který není zastoupen žádnou současnou techologií. Dal by se přirovnat k nástupci technologie Full Motion Video (taktéž zmíněné v úvodu). Využívá ovšem moderních postupů a standardů. A formát jeho videa zůstává kompatibilní se současným standardem MPEG-4.
28
KAPITOLA 5. ZÁVĚR
KAPITOLA 6. LITERATURA
29
6 Literatura [1] Dokumentace ffmpeg. [online], [cit. 28.5.2008]. http://ffmpeg.mplayerhq.hu/ffmpeg-doc.html. [2] Tutoriál ffmpeg. [online], [cit. 28.5.2008]. http://www.dranger.com/ffmpeg/. [3] Proprietální řešení interaktivního videa. [online], [cit. 28.5.2008]. http://www.immersivemedia.com/. [4] Blu-ray interaktivní film. [online], [cit. 28.5.2008]. http://blu-ray.cz/2007/11/navrat-do-domu-hruzy-return-to-house-on-haunted-hill-blu-ray-disc/. [5] Full Motion video. [online], [cit. 3.6.2008]. http://en.wikipedia.org/wiki/Full_motion_video. [6] Quicktime VR. [online], [cit. 3.6.2008]. http://www.apple.com/quicktime/technologies/qtvr/. [7] Rozpaky kuchaře Svatopluka. [online], [cit. 27.5.2008]. http://www.televize.cz/scripts/detail.php?id=23305. [8] Kinoautomat. [online], [cit. 27.5.2008]. http://www.kinoautomat.cz/. [9] DVD. [online], [cit. 27.5.2008]. http://cs.wikipedia.org/wiki/DVD_Video. [10] Specifikace MPEG-4. [online], [cit. 27.5.2008]. http://www.chiariglione.org/mpeg/. [11] MPEG-4 - Wikipedie. [online], [cit. 27.5.2008]. http://en.wikipedia.org/wiki/MPEG-4. [12] MPEG-4 Part 14 na Wikipedii. [online], [cit. 27.5.2008]. http://en.wikipedia.org/wiki/MPEG-4_Part_14. [13] Rozšíření formátu MPEG-4. [online], [cit. 27.5.2008]. http://rodeo.ic.cz/mp4/. [14] R. Šoustal. Rozšíření formátu MPEG pro stereoskopické video. 2006. bakalářská práce.
30
KAPITOLA 7. PŘÍLOHA
7 Příloha 7.1 7.1.1
Instalace a použití programu Kompilace
Zájemce si může program sám zkompilovat. To lze však pouze na operačním systému Linux (důvody viz. kapitola 3.1.1). Samotná kompilace se provádí standardně příkazem make. Pro kompilaci jsou potřeba balíčky libavcodec-dev, libavformat-dev, libavutil-dev a libswscale-dev. 7.1.2
Instalace
Program pro svůj běh potřebuje funkce z projektu ffmpeg. Jejich přidání do systému lze provést například na systémech odvozených od distribuce Debian příkazem (s právy roota) apt-get install libavcodec libavformat libavutil libswscale. Spouštět se dá, jak již bylo zmíněno, pouze v operačním systému Linux s podporou OpenGL. Instalace samotná není potřeba, program je reprezentován jedním spustitelným souborem (player). 7.1.3
Ovládání
Program se spouští a ovládá pouze v konzoli, grafické rozhraní nebylo nutné, ani žádoucí. Pro spuštění napíšeme do konzole příkaz (předpokládá umítění v adresáři s programem): ./player FILE [d] • ./player - jméno spouštěného programu • FILE - místo tohoto musíme napsat cestu k video souboru, který chceme spustit • d - volitelný přepínač, pokud ho zadáme, přehrávač se spustí na celou obrazovku, jinak se přehrává v okně Ovládání přímo v programu je popsáno v kapitolách 3.4.1.1 a 3.4.1.2.
KAPITOLA 7. PŘÍLOHA 7.1.4
Obsah CD
• DATA – scene.mp4 - testovací soubor s videem – scene.mp4.sw - soubor s informacemi o odbočení • EXE – player - zkompilovaný program • SRC – Makefile - soubor s informacemi o kompilaci – *.* - zbytek souborů v adresáři jsou zdrojové kódy projektu • TEXT – bp.pdf - text bakalářské práce ve formátu pdf – bp.ps - text bakalářské práce ve formátu ps
31