TLC group - Home - Università degli Studi di Ferrara
Transcript
TLC group - Home - Università degli Studi di Ferrara
Università degli Studi di Ferrara FACOLTÀ DÌ INGEGNERIA CORSO DÌ LAUREA SPECIALISTICA IN INGEGNERIA INFORMATICA E AUTOMAZIONE Sincronizzazione di contenuti multimediali Laureando Relatore ALEX FRIGNANI GIANLUCA MAZZINI ____________________________________ _____________________________________ (firma) (firma ) Anno accademico 2007/2008 INDICE Introduzione ................................................................................................................................... 4 Formati Contenitori......................................................................................................................... 6 1.1 Audio Video Interlave (AVI) ............................................................................................... 7 1.1.1 RIFF file format .......................................................................................................... 7 1.1.2 Formato AVI RIFF ....................................................................................................... 8 1.1.3 AVI 2.0 ....................................................................................................................... 9 1.2 OGG ................................................................................................................................ 11 1.3 MPEG Transport Stream.................................................................................................. 13 1.3.1 1.4 PROGRAM SPECIFIC INFORMTION (PSI) ................................................................... 16 Program Stream .............................................................................................................. 17 INCAPSULATORI ............................................................................................................................ 18 2.1 Multimedia Home Platform ............................................................................................ 18 2.1.1 Xlet .......................................................................................................................... 20 2.1.2 Profili ....................................................................................................................... 21 2.2 Compact Disc (CD)........................................................................................................... 21 2.3 Digital Versatile Disc (DVD) ............................................................................................. 23 2.4 Blu-Ray Disc .................................................................................................................... 26 Tool............................................................................................................................................... 29 3.1 FFMPEG .......................................................................................................................... 29 3.1.1 Simple DirectMedia Layer (SDL) ............................................................................... 30 3.1.2 Formati supportati ................................................................................................... 31 3.2 MEncoder e Mplayer....................................................................................................... 31 3.2.1 3.3 Formati supportati ................................................................................................... 32 Video Lan ........................................................................................................................ 33 3.3.1 Formati supportati ................................................................................................... 34 3.3.2 Struttura modulare di VLC........................................................................................ 35 Analisi del problema e ambiente di Lavoro .................................................................................... 39 Applicazione.................................................................................................................................. 42 5.1 H.264/X.264 .................................................................................................................... 43 5.1.1 Profili ....................................................................................................................... 44 2 5.1.2 Utilizzo di X.264 ....................................................................................................... 45 5.2 File sorgente e il problema dei sottotitoli ........................................................................ 46 5.3 Il parsing ......................................................................................................................... 48 5.4 L’Encoder dei sottotitoli .................................................................................................. 52 5.5 Transport Stream Multiplexer e Demultiplexer ............................................................... 53 5.6 Il decoder di sottotitoli .................................................................................................... 54 5.6.1 La decodifica del flusso ............................................................................................ 55 Conclusioni ................................................................................................................................... 58 Bibliografia .................................................................................................................................... 59 3 Introduzione La multimedialità è la compresenza e interazione di più mezzi di comunicazione in uno stesso supporto o contesto informativo. Si parla di contenuti multimediali, specie in ambito informatico, quando per comunicare un'informazione si utilizzano molti media diversi: immagini in movimento (video), immagini statiche (fotografie), musica e testo. Il termine multimedialità o multimediale, diffuso tra la fine degli anni ottanta e l'inizio degli anni novanta, deriva al latino medium (= "mezzo", qui inteso come mezzo di comunicazione) e si può grossolanamente tradurre in "con molti mezzi". Talvolta la multimedialità viene confusa con l'interattività, con la quale invece non ha niente a che fare, almeno non direttamente. La confusione nasce dal fatto che spesso la multimedialità è affiancata dall' interattività. L'Interattività è la caratteristica di un sistema il cui comportamento non è fisso, ma varia al variare dell'input dell'utente. Quando l'utente trasmette, in un modo qualunque, un'informazione al sistema che sta utilizzando, interagisce con esso; grazie a questa interazione, il sistema può deviare dal suo comportamento prefissato ed adeguarsi alle esigenze dell'utente. La maggior parte dei sistemi con cui si ha a che fare è generalmente interattiva: una lavatrice è interattiva, in quanto modifica il suo comportamento a seconda di come regoliamo le sue manopole e pulsanti. Un computer è interattivo perché ci mostra questo o quell'altro dato a seconda delle informazioni che gli forniamo tramite il mouse o la tastiera. Un esempio di sistema non interattivo è invece la televisione analogica, ossia la televisione classica, l'unica in effetti disponibile da cinquant'anni fa fino a pochi anni fa, prima dell'avvento della TV digitale. La televisione classica ha una fruizione pressoché completamente passiva: a parte il cambio dei canali e del volume, non è possibile far altro all'utente, che non può ad esempio comunicare con l'emittente per richiedere una particolare trasmissione, cosa che invece è possibile con la moderna TV digitale. Le informazioni fornite dall'utente al sistema tramite interazione vengono talvolta chiamate feedback. La televisione nasce come comunicazione unidirezionale dal provider televisivo all'utente, cioè l'utente non ha la possibilità di interagire con la televisione. L'editore dell'emittente televisiva decide i programmi televisivi di cui deve fruire l'utente e tutti gli utenti fruiscono dei medesimi programmi televisivi nel medesimo istante. L'unica forma di interazione dell'utente con la televisione è la possibilità di scegliere l'emittente televisiva tra quelle disponibili. Con il passare degli anni e il progredire della tecnologia, in particolare di quella digitale, iniziano ad essere disponibili i primi servizi televisivi attraverso cui l'utente interagisce con la televisione, tali servizi sono chiamati servizi interattivi. Oggi i moderni standard televisivi per la televisione digitale, non pongono limiti alle possibilità di interazione dell'utente con la televisione, gli unici limiti sono dati dalle capacità e dalla creatività degli sviluppatori dei servizi interattivi; inoltre i moderni standard prevedono anche la televisione 4 ad alta definizione con risoluzione verticale dell'immagine televisiva di 720 e 1080 pixel, aumentando quindi la qualità sia dell’audio che del video. Per veicolare i flussi audio, video e applicazioni è necessario inserire il tutto all’interno di un formato contenitore. I più comuni formati contenitori utilizzati oggi sono AVI, ASF, WAV, TS, PS, MOV, MKV, OGG. Spesso si fa molta confusione su cosa sia in realtà un formato contenitore. Per comprendere meglio il concetto si potrebbe paragonare il formato contenitore ad un pacco postale o ad un regalo. Noi non siamo interessati alla scatola in sé, ma vogliamo vedere cosa contiene, cosa c’è all’interno. Per questo motivo utilizziamo per esempio un coltello per aprirla. Un formato contenitore segue la stessa idea. Infatti il formato contenitore contiene al suo interno diversi flussi codificati attraverso opportuni codec. Se ci troviamo davanti ad un file AVI e vogliamo riprodurlo, dobbiamo prima aprire la nostra scatola, dobbiamo cioè utilizzare il codec opportuno per decodificare i vari flussi all’interno del file AVI. In questa tesi si è cercato di sviluppare qualcosa di diverso e innovativo. Si è cercato di inserire all’interno di un formato contenitore come il transport stream un flusso video codificato in h.264 (codifica utilizzata per i video in alta definizione), un flusso audio e un’applicazione non utilizzando le tecnologie impiegate per esempio nella televisione digitale come mhp. Inserire un flusso audio, un flusso video e un applicazione all’interno di un formato contenitore come il transport stream, utilizzando questa tecnologia, sarebbe stato molto complesso e il risultato sicuramente non ottimale. Sono state scartate anche diverse soluzioni Java, in quanto il risultato finale sarebbe stato sicuramente poco performante. L’attenzione così si è spostata su VLC. L’idea implementata che verrà analizzata in dettaglio in seguito è quella di sfruttare il flusso di sottotitoli per inserire il sorgente di un programma e di multiplexare quindi il flusso video in h264, l’audio e i sottotitoli modificati all’interno di un transport stream. In un secondo momento il transport stream sarà demultiplexato, saranno estratte le informazioni dal flusso di sottotitoli, compilato il programma e poi eseguito; il tutto durante la riproduzione del video e dell’audio. Per realizzare questa tesi un ringraziamento va alla mia famiglia, che mi ha messo a disposizione tutte le risorse necessarie per consentirmi di intraprendere al meglio il mio percorso di studi. Un grazie particolare al prof. Mazzini; la sua collaborazione mi ha permesso di trovare la strada migliore per implementare questa applicazione. 5 1. CAPITOLO Formati Contenitori Un formato contenitore è un file che può contenere vari tipi di dato compressi utilizzando diversi codec audio e video. Il file contenitore è utilizzato per eseguire l’interleave di diversi tipi di dato. I file contenitori più semplici possono contenere differenti tipi di codec audio, mentre i più complessi possono supportare uno stream video e audio multiplo, sottotitoli, informazioni sui capitoli. Tutti questi componenti devono essere accompagnati da opportune informazioni di sincronizzazione in modo da essere riprodotti insieme. Il codec è un dispositivo o spesso un applicativo software capace di codificare e decodificare uno stream di dati digitali. La parola codec infatti deriva da compressor/decompressor oppure coder/decoder. Il tipo di compressione realizzata dai codec può essere di due tipi: - Lossy: Sono i codec più utilizzati e riducono la qualità di quello che comprimono guadagnando però dal punto di vista della compressione e dello spazio occupato. Lossless: Questi codec mantengono tutto il contenuto informativo presente nello stream originale, la compressione quindi è senza perdita di informazioni. Vengono utilizzati quando è più importante preservare la qualità a scapito dell’occupazione di memoria. I diversi formati contenitori possono differenziarsi tra di loro per diverse caratteristiche: - Popolarità: quanto il contenitore è conosciuto o supportato - Overhead: La differenza in termini di dimensioni di un file con lo stesso contenuto informativo in due diversi contenitori - Supporto per le avanzate funzionalità dei codec: i contenitori più vecchi come gli AVI non sono in grado di supportare i B-frames (Bi – directional predictive pictures), una bitrate variabile per l’audio e una framerate variabile per il video. Tutto questo può essere aggirato modificando il formato creando problemi di compatibilità. - Supporto per contenuti avanzati come capitoli, sottotitoli, tag, dati utente. - Supporto per lo streaming. In seguito verranno descritti i contenitori più utilizzati. 6 1.1 Audio Video Interlave (AVI) Il formato multimediale AVI è stato introdotto da Microsoft nel Novembre del 1992 e può contenere dati sia audio che video permettendo la loro riproduzione in maniera sincrona. Il formato AVI è un caso particolare di un formato più generale chiamato Resource Interchange File Format (RIFF). I dati vengono suddivisi e memorizzati in blocchi chiamati chunk. Ogni chunk è composto da un campo di 4 byte chiamato Four Character Code (FourCC), che indica la tipologia del chunk, da un campo di 4 byte che indica la lunghezza del campo dati successivo e ovviamente il campo dati di lunghezza variabile. Il campo FourCC è un 32-bit unsigned integer creato per concatenazione di 4 caratteri ASCII. Per esempio il FourCC ‘abcd’ sarà 0x64636261. Questi codici servono per identificare i tipi di stream, i chunk, le entries dell’indice e altre informazioni. 1.1.1 RIFF file format Un file RIFF è costituito da un header e da zero o più lists e chunk. L’ header ha la seguente struttura: ‘RIFF’ fileSize fileType (data) RIFF è letteralmente il FourCC code di RIFF, fileSize è un campo a 4 – bit che indica le dimensioni dei dati nel file, e fileType è il FourCC che indica il particolare tipo di dato presente nel file. Il campo fileSize indica la dimensione del campo fileType più i dati che seguono. I dati sono un insieme di chunk e liste in qualsiasi ordine. Un chunk ha la seguente forma: ckID ckSize ckData Il ckID è il FourCC che indica il tipo di dati contenuti nel chunk, ckSize è un valore di 4 byte che mi indica la lunghezza del campo data e ckData rappresentano zero o più byte di dato. Ai dati viene sempre aggiunto un padding per avere sempre delle word (32 bit) Una lista ha la seguente forma: ‘LIST’ listeSize listType listData LIST è il FourCC di LIST, listSize è un valore a 4 bit che indica la dimensione della lista, listType è un FourCC, mentre listData è costituito da chunk di liste in qualsiasi ordine. 7 1.1.2 Formato AVI RIFF I file AVI sono identificati dal FourCC ‘AVI’ all’ interno del header del file RIFF. Tutti gli avi contengono due chunk lista, che definiscono il formato dei vari stream a cui si riferiscono. Un avi file può anche contenere un indice, che indica la disposizione dei vari chunk dato presenti all’interno del file. La struttura di un file avi è quindi la seguente: RIFF ('AVI ' LIST ('hdrl' 'avih'(<Main AVI Header>) LIST ('strl' 'strh'(<Stream header>) 'strf'(<Stream format>) [ 'strd'(<Additional header data>) ] [ 'strn'(<Stream name>) ] ... ) ... ) LIST ('movi' {SubChunk | LIST ('rec ' SubChunk1 SubChunk2 ... ) ... } ... ) ['idx1' (<AVI Index>) ] ) ‘hdrl’ definisce il formato dei dati ed è la prima lista obbligatoria. Il campo ‘movi’ contiene dati per la sequenza avi ed è la seconda lista obbligatoria. ‘idx1’ contiene invece l’indice. All’interno di un file avi questi componenti devono essere mantenuti nella giusta sequenza. Hdrl inizia con un main AVI header, che è contenuto in un chunk avih. Il main header contiene informazioni globali sul file avi, come ad esempio il numero di stream all’ interno del file o larghezza e altezza della sequenza avi. Prendendo in considerazione i stream header notiamo che una o più liste strl seguono il main header. È obbligatoria una lista strl per ogni stream. Ogni strl contiene informazioni riguardo lo stream del file e deve contenere uno stream header chunk (strh) e uno stream format chunk (strf) che descrive il formato dei dati nello stream. Opzionalmente strl può contenere anche un stream header data chunk (strd) il cui formato e contenuto sono definiti dal codec e uno stream name chunk (strn). Gli stream header nella lista hdrl sono associati con gli stream dato nella lista movi in base all’ordine dei chunk strl; infatti il primo chunk strl sarà associato allo stream zero, il secondo chunk strl allo stream 1 e così via. 8 La lista movi contiene i dati attuali presenti nello stream come ad esempio i frame video o i campioni audio. I chunk dato si possono trovare direttamente all’interno della lista movi oppure raggruppati utilizzando la lista rec. Questo significa che tutti i chunk del gruppo devono essere letti insieme. I FourCC che identificano i vari chunk di dati sono costituiti da due cifre che corrispondono al numero dello stream e da un particolare codice che definisce il tipo di dato presente nel chunk; ad esempio: - db: uncompressed video frame dc: compresse video frame pc: palette change wb: audio data Quindi se il stream 0 conterrà solo audio, si avrà un FourCC ‘00wb’ . Se il stream 1 contiene video, si avrà per esempio ‘01db’. Esistono due tipi di file avi. Nel primo esiste un unico stream di dati; per questo motivo l’audio e il video vengono memorizzati in maniera interlacciata, formando un unico stream digitale. Si utilizza questo tipo quando si vuole ottimizzare l’occupazione di memoria. Dovrà essere utilizzato quindi un mixer in codifica e uno splitter in decodifica. Nel secondo tipo di file avi si hanno invece stream audio e video separati. 1.1.3 AVI 2.0 Nel novembre del 1995 il consorzio Open Digital Media (OpenDML) ha definito un nuovo formato avi. Gli obbiettivi principali erano quelli di garantire una interoperabilità e compatibilità con la versione dei file avi precedentemente fornita da Microsoft, aggiungendo però un supporto a file di dimensioni più grandi, una indicizzazione dei frame e dei campi, un migliore meccanismo di interleaving per l’audio e il video. Il formato RIFF permetterebbe al file AVI di raggiunger dimensioni di 4gb perché la dimensione è memorizzata attraverso un valore a 32 bit, ma il parser del file RIFF e alcune limitazione del file avi consentono una dimensione massima di circa 1gb. Questa limitazione può essere superata inserendo più chunk RIFF all’ interno dello stesso file. Le informazioni che un file avi supera la dimensione massima consentita devono essere inserite nell’extend AVI header. I RIFF aggiuntivi sono identificati da un AVIX chunk id. I chunk AVIX possono contenere solamente la lista movi, mentre tutte le altre informazioni sono contenute all’interno del primo chunk RIFF 9 Figura 1.1 Estensione del File AVI a dimensioni superiori ad 1GB Il file avi tradizionale dava la possibilità di inserire un campo idx1, che contiene una lista di offset e tipi di dato dei vari chunk. Questa lista viene utilizzata per riprodurre il file avi e scorrerlo in maniera più efficiente in quanto non importa scorrere tutte le sotto liste del chunk movie per sapere la posizione del frame video. Questa struttura indice però limita la dimensione del file; in AVI 2.0 invece si utilizza una struttura costituita da un indice generale che punta a dei sottoindici che si trovano all’interno delle liste ‘movi’, risolvendo quindi i problemi dovuti alle limitazioni precedenti. La struttura dell’indice che si ottiene è quindi la seguente: Figura 1.2 Struttura indice in AVI 2.0 10 1.2 OGG Il progetto è stato sviluppato originariamente da Christopher Montgomery della Xiph.Org Foundation. La vera etimologia del termine deriva da uno slang coniato dallo stesso Montgomery in riferimento alla pesantezza dell'algoritmo Vorbis ai tempi della sua nascita. Riprendendo il nome di una tattica del videogioco Netrek che consisteva in un attacco suicida, è diventato di uso comune l'espressione inglese to ogg con il significato approssimativo di "intraprendere un'azione azzardata, con esiti incerti e conseguenze probabilmente deleterie". Lanciare un processo di codifica di un brano musicale in Ogg Vorbis, al tempo, rendeva infatti totalmente inutilizzabile il computer per diversi minuti. Ogg è un formato per il trasporto di flussi di bit progettato per permettere sia lo streaming che l'archiviazione in maniera efficiente. Il nome "Ogg" si riferisce al formato di file, che include un numero di codec indipendenti per il video, l'audio ed il testo (ad esempio, per i sottotitoli). I file con l'estensione ".ogg" possono contenere uno qualsiasi dei formati supportati, e poiché il formato è liberamente implementabile, i vari codec ogg sono stati incorporati in molti riproduttori multimediali, sia proprietari, sia liberi. Spesso il termine "ogg" è stato usato per indicare il formato di file audio Ogg Vorbis, cioè un file audio codificato in un file ogg con l'algoritmo Vorbis, poiché questo è stato il primo codec ad usare il contenitore ogg. Altri importanti codec sviluppati per il contenitore ogg sono Theora per la compressione video, e Speex, una algoritmo ottimizzato per la compressione del parlato. Uno stream fisico Ogg è costituito da multipli stream logici interlacciati che contengono chunk chiamati pagine. I stream logici sono identificati da un unico codice seriale memorizzato nell’header di ciascuna pagina. Questo codice è generato random e non ha nessun collegamento con il contenuto della pagina. Le pagine di uno stream logico sono interlacciate e non importa che siano in un ordine particolare, basta che siano consecutive all’interno dello stream. Ogni pagina contiene solo un tipo di dato e sono di dimensione variabile. L’header conterrà informazioni per quanto riguarda l’incapsulamento e la correzione di errori. Ogni stream logico all’interno di uno stream fisico inizierà con una pagina speciale di inizio (bos: beginning of stream) ed una di fine (eos: end of stream). La pagina ‘bos’ contiene informazioni per identificare il tipo di codec e opzionalmente può contenere informazioni per configurare il processo di codifica. Uno stream fisico quindi inizierà con le pagine ‘bos’ di tutti gli stream logici, successivamente si avranno gli header dei pacchetti di tutti gli stream e infine le pagine contenenti i dati. Di seguito viene riportata la struttura dell’header di una pagina 11 BIT 0-7 BIT 8-15 BIT 16-23 BIT 24 31 CAPTURE PATTERN VERSION Byte 0-3 HEADER TYPE Granule Position Byte 4-7 Byte 8-11 Bitstream serial number Byte 12-15 Page sequence number Byte 16-19 Checksum Byte 20-23 Page segment Segment table Byte 24-27 Byte 28 Figura 1.3 Struttura header di una pagina in formato OGG - - Capture Pattern: Questo campo è di 32 bit e viene anche chiamato codice di sincronizzazione e viene usato per assicurare il sincronismo durante il parsing di un file OGG. Version: Campo di 8 bit che indica la versione utilizzata Header Type: è un flag che indica il tipo di pagina. Se il bit è settato a zero (valore 0x01) la pagina sarà una continuazione del pacchetto precedente, se settato a 1 (valore 0x02) la pagina sarà una bos, mentre se settato a 2 (valore 0x02) la pagina sarà una eos. Granule position: Campo a 64 bit, è il marcatore temporale del file ogg, il suo valore è astratto infatti il suo significato cambia a seconda del codec utilizzato. Bitstream Serial Number: Campo di 32 bit, questo numero seriale identifica a quale bitstream logico appartiene la pagina Page sequence number: Campo di 32 bit, viene incrementato dopo ciascuna pagina, quindi la prima pagina avrà valore 0, la seconda 1,ecc..Serve per capire quando un dato viene perso. Checksum: Campo a 32 bit,verifica che i dati non siano stati corrotti da quando vengono creati. Page segments: Campo a 8 bit, indica quanti segmenti sono presenti nella pagina; il numero massimo di segmenti è di 255. Segment Table: Vettore a 8 bit che indica la lunghezza di ciascun segmento. La lunghezza varia da 0 a 255 bytes Le specifiche di incapsulamento per uno o più bitstream logici viene chiamata media mapping. Esisistono due tipi differenti di multiplexing: - Multiplexing concorrente o Grouping Multiplexing sequenziale o Chaining Nel grouping, tutte le pagine bos di tutti i bitstream logici devono essere raggruppate insieme all’inizio del bitstream fisico OGG. Il media mapping specificherà l’ordine delle pagine iniziali. Le 12 pagine eos non importa che siano contigue e potrebbero anche non contenere dati ma solo informazioni sulla posizione che sono inerite nell’header. Nel chaining i bitstream logici sono concatenati; per esempio la pagina eos viene seguita dalla pagina bos dello stream seguente. Di seguito viene mostrato un esempio di due stream fisici ogg concatenati rispettando quindi le regole del grouping e chaining. A B C A A C B bos bos bos A B A C eos B C B eos C D bos D D eos Qui abbiamo due bitstream fisici, il primo è un gruppo di tre bitstream logici A,B,C; infatti le pagine bos sono le prime del flusso. Il secondo bitstream viene concatenato dopo la fine del primo. Le pagine bos devono comparire prima delle pagine dato. MPEG Transport Stream 1.3 Il transport stream è un protocollo di comunicazione per audio,video e dati. Questo permette di multiplexare audio e video digitali e di sincronizzarli tra di loro. Il transport stream offre caratteristiche di correzione degli errori per il trasporto su canali non affidabili; proprio per questo motivo è molto utilizzato in applicazioni broadcast come il DVB. Il TS è un formato contenitore e incapsula stream elementari divisi in pacchetti e altri dati. Il TS è processato dal ricevitore per livelli, simili ai livelli ISO/OSI di rete: - Composizione dei vari programmi Packetized elementary stream (PES) Elementary stream (ES): ad esempio audio e video Group of pictures (GOP) Slice: Previene la propagazione di un errore Macroblock: è costituito da 6 o 12 DCT block Codifica di blocco: codifica DCT di un blocco, 8x8 pixels Il transport stream quindi è il risultato del multiplexing di pacchetti chiamati PES (Packetized Elementary Stream) che sono ottenuti dai flussi multimediali elementari detti ES (Elementary Streams) contenenti i dati audio e video compressi e altro (ad es. sottotitoli, o dati per servizi interattivi ed anche datagrammi IP). Nello stesso multiplex sono inviate anche le informazioni che servono per gestire le associazioni fra tali dati e descriverli. Sono dette PSI (Program Specific Informations). 13 Gli ES sono gli stream dei dati video compressi (frame I,P,B), dell’audio, e di alcune informazioni come i sottotitoli. Ogni ES viene suddiviso in pacchetti detti PES. I PES possono essere associati e nell’insieme formare un programma ad esempio costituito da più flussi video (es: inquadrature multiple), più tracce audio (es: audio multilingua) ed infine i sottotitoli. Non ci sono specifiche sulla dimensione di questi pacchetti, che possono essere di lunghezza variabile per contenere un intero frame video, oppure di lunghezza fissa. Gli header dei PES contengono la descrizione del tipo di contenuto e le informazioni per la sincronizzazione. I PES e le PSI Sections attraverso multiplazione sono raccolti in un unico stream . VIDEO VIDEO ENCODER ES AUDIO AUDIO ENCODER ES DATA PACKETIZER PES 1 PACKETIZER PES 2 PACKETIZER/ FORMATTER PES 3 TRANSPORT MULTIPLEX TS PSI Figura 1.4 Funzionamento di un Transport Stream I PES e le PSI sections, per la multiplazione, vengono suddivisi in pacchetti di 184 byte recanti 4 byte aggiuntivi di header. Sono i Transport Packets (188 byte) che vanno a costituire il TS. E' specificato che un pacchetto PES deve sempre cominciare all'inizio del payload di un transport packet e che ogni transport packet deve contenere dati provenienti da un unico pacchetto PES. Per questo motivo eventuale spazio rimanente in un transport packet che non è stato riempito deve essere lasciato così e completato solo da stuffing bytes inseriti in uno specifico campo detto Adaptation Field. Di seguito viene riportata la struttura dell’header di un transport packet: 14 Figura 1.5 Header pacchetto TS - - - Sync byte: 8 bit con valore costante 0x47 (1000 1111). Definisce l’inizio di un transport packet e permette la sincronizzazione della trasmissione. Transport Error Indicator: indica che il pacchetto è danneggiato. Payload unit start indicator: settato quando il TS contiene l’inizio di un PES. Transport Priority: Serve per dare una certa priorità a certi pacchetti di un ES. PID: Campo a 13 bit. È un sistema di mappatura che differenzia i pacchetti e raggruppando quelli con lo stesso PID identifica quali trasportano un determinato flusso di informazioni, ad esempio il video di un certo programma , o l'audio in una certa lingua, o dati di servizio come le PSI tables. Transport scrambling control: tipo di cifratura utilizzata. Adaptation field control: Indica se è presente il campo adaptation field oppure no. Continuity counter: è un contatore di continuità tra le sezioni PES. Questo contatore è un campo di 4 bit che viene incrementato in maniera ciclica ogni volta che un nuovo Transport Stream packet dello stesso ES viene generato. Permette di rilevare se sono stati persi dei pacchetti TS. Adaptation field: è un estensione dell’header non sempre presente in ogni transport packet e contiene a sua volta diversi campi. Di seguito invece viene riportata la struttura del campo adaptation field: - Adaptation field length: 8bit, indicano il numero di bytes presenti nell’adaptation field che seguono questo byte. Discontinuity indicator: 1bit, viene settato ad 1 se si verifica una discontinuità nei transport packet. Random Acccess indicator: 1bit, settato ad 1 se il pacchetto PES inizia con una sequenza audio/video. Elementary stream priority indicator: 1bit, se 1 implica alta priorità. PCR flag: 1bit, se vale 1 adaptation field contiene un campo PCR. OPCR flag: 1bit. Splicing point flag: 1bit. Transport private data flag: 1bit, se vale 1 segnala la presenza di dati privati all’interno dell’adaptation field. Adaptation field extension: 1bit, se 1 indica la presenza di estensioni all’adaptation field PCR: 33+9 bit, clock del transport stream. OPCR: 33+9 bit, utile quando un transport stream viene accoppiato con un altro; questo campo mantiene il PCR originale del TS. 15 - Splice countdown: 8bit, indica dopo quanti transport packet è presente un punto di unione. Stuffing bytes: lunghezza variabile. 1.3.1 PROGRAM SPECIFIC INFORMTION (PSI) Le PSI sono le informazioni che servono per descrivere e associare attraverso i PID, i vari PES e di conseguenza i flussi elementari che vanno a costituire un programma. Strutturalmente sono delle tabelle di associazione (PSI Association Tables) che vengono inviate periodicamente dopo essere state suddivide in sezioni (PSI Sections) e pacchettizzate nel TS allo stesso modo dei PES. Per l’importanza dell’integrità delle informazioni delle tabelle, spesso le PSI Sections sono protette da CRC. Di seguito vengono descritte le varie tabelle esistenti: - - PAT (Program Association Table): è al livello più alto nella gerarchia delle tabelle, contiene la lista completa di tutti i programmi nel TS che sono identificati attraverso un numero detto Service Identification (SID) e i PID delle rispettive Program Map Tables. I pacchetti che la contengono sono identificati dal PID 0 PMT (Program Map Table): Contiene la lista dei PID audio e video associati ad un certo programma e il pid della Program Clock Reference (PCR) PCR: permette una ricostruzione di una base temporale coerente per i programmi. È un campo di 42 bit presente nell’adaptation field, oppure in un PID video. Programma 0 PID 10 VIDEO 1 PID 70 Programma 1 PID 20 AUDIO 1 PID 80 Programma 2 PID 30 AUDIO 2 PID 90 PAT (PID 0) PMT del Programma 2 (PID 30) Al video 1 può essere associata una PCR (PID 70) Figura 1.6 Esempio di tabella PAT e PMT 16 1.4 Program Stream Il formato contenitore Program Stream (PS) è molto simile al transport stream e serve per multiplexare audio video e dati. Lo stream viene creato unendo tra di loro più Packetized elementary stream (PES) che hanno una base temporale in comune fra di loro. Viene utilizzato su media come CD o DVD, in contrasto con il transport stream che viene utilizzato su canali di trasmissione con un alta percentuale di errore. Proprio per questo motivo si ha dimensione dei record variabile e poche parole di sincronizzazione rendendo difficile appunto la ricezione di stream via satellite, ma questo metodo garantisce basso overhead. 17 2 CAPITOLO INCAPSULATORI 2.1 Multimedia Home Platform Il multimedia home platform (MHP) è un middleware standard progettato per il DVB per fornire servizi interattivi sulla televisione digitale. MHP abilita l’esecuzione di applicazioni interattive JAVA-based. Le applicazioni TV interattive possono essere distribuite utilizzando un canale broadcast, insieme ovviamente agli stream audio e video. Queste applicazioni possono essere ad esempio informazioni di servizio, giochi, SMS, e-mail. Ovviamente per una completa interazione è necessario un canale di ritorno delle informazioni. I canali più tipici sono un collegamento tramite presa telefonica oppure utilizzando una rete internet. Negli ultimi anni in Europa nazioni come Italia, Finlandia, Austria, Germania, Svezia, Danimarca, Spagna stanno investendo molto sulla tv interattiva cercando di aumentare il numero di decoder e di standardizzare sempre più questa tecnologia. Negli Stati Uniti viene utilizzato OCAP al posto dell’MHP per privilegiare le trasmissioni via cavo, mentre in Sud Korea vengono utilizzate entrambe. Come detto in precedenza MHP è un middleware. Per middleware si intende, in reti avanzate, quei servizi e altre risorse localizzate tra le applicazioni e il sottostante pacchetto di forwarding e routing dei messaggi, dell’infrastruttura. Non esiste comunque una precisa linea di demarcazione che definisce questo dominio. In pratica il termine middleware sta ad indicare tutte quelle librerie ad alto livello che facilitano lo sviluppo di un’applicazione fornendo servizi generici utili non solo per un’applicazione ma per una varietà di applicazioni, per esempio comunicazione, accesso ai dati, codifica, controllo delle risorse. Questi stessi servizi vengono offerti dal sistema operativo, ma l’idea è quella di rendere tutto questo indipendente dal sistema operativo in modo da permettere la riusabilità dei blocchi. Tutto questo serve per ridurre il tempo di sviluppo di un applicazione. 18 Servizi E applicazioni SERVIZI E APPLICAZIONI MIDDLEWARE Middleware LIVELLO DI COMUNICAZIONE Piattaforma S.O. S.O. S.O. HW HW HW Figura 2.1 Architettura di un middleware Per quanto riguarda MHP avremmo quindi 3 livelli: - Piattaforma: processore MPEG, dispositivi I/O, CPU, memoria, processore grafico. Middleware: JVM, API, protocollo di trasporto e application manager, chiamato anche navigatore, che permette i gestire l’esecuzione di applicazioni JAVA. - Servizi e Applicazioni: sono le applicazioni interattive: TV commerce, TV banking, Electronic Program Guide, servizi informativi (meteo, traffico, news, etc...), giochi, sport, e via dicendo. MHP si basa sul protocollo DSM – CC (Digital Storage Media Command And Control). In questo protocollo bisogna prendere in considerazione tre componenti: Un server che fornisce servizi ad un client e entrambi sono client del SRM (Resource Manager) che gestisce le risorse di rete come banda, indirizzi, ecc.. Questo protocollo permette di trasferire informazioni da un server ad un client, sia all’interno di un MPEG Transport Stream o in un canale separato ad alta velocità. Sul server è presente un oggetto autonomo chiamato data carousel che ciclicamente manda le informazioni. Il client download carousel ovviamente rimarrà in attesa delle informazioni. Un estensione del data carousel è l’object carousel, che presenta le informazioni come oggetti compatibili con le API definite dall’ utente. I dati trasmessi sono separati in moduli di 64kb e vengono trasmessi sequenzialmente; ovviamente l’applicazione potrà essere visualizzata solo dopo aver ricevuto tutti i moduli. La trasmissione dei dati è ripetuta ciclicamente con un periodo di ripetizione pari al quoziente della quantità totale in byte di dati da trasmettere divisa per la velocità di trasmissione disponibile. Per sviluppare applicazioni MHP esistono due approcci: o si acquista un sistema di sviluppo da un venditore MHP, oppure si utilizzano degli emulatori come XletView o OpenMHP. Il trasferimento delle applicazioni su differenti Set Top Box è indispensabile poiché STB diversi si comportano in modo diverso anche se la linea guida dello standard MHP miri all’interoperabilità del sistema e quindi a far si che un’applicazione generi identici risultati sui differenti STB. 19 2.1.1 Xlet Xlet è un’applicazione Java simile ad un applet. Ogni Xlet è trasmessa in broadcast ciclicamente e costantemente (broadcast carousel) ed è solitamente associata ad un particolare canale tv (i dati e lo streaming audio video vengono multiplexati). L’application Manager si occuperà poi di caricare ed eseguire l’applicativo Xlet, segnalando all’utente la lista delle applicazioni MHP disponibili sul canale televisivo e caricando i componenti relativi all’applicazione. Per poter interagire con l’application manager vengono usate le librerie messe a disposizione dalle API. Il ciclo di vita di un’applicazione Xlet è il seguente: initXlet() LOADED startXlet() STARTED PAUSED destroyXley() pauseXlet() DESTROYE D destroyXlet() Figura 2.2 Ciclo di vita Xlet - - - L’application manager carica il main della classe Xlet e crea un istanza chiamando il costruttore di default. Quando questo accade l’applicazione è nello stato Loaded. Quando l’utente sceglie di avviare l’applicazione, l’application manager chiama sul ricevitore il metodo initXlet(). A questo punto lo Xlet cambia contesto e precarica grosse quantità di dati come le immagini che richiedono tempo per caricarsi dall’object carousel. Quando l’inizializzazione è completata, l’applicazione è nello stato Paused ed è pronta per essere eseguita immediatamente. Quando il metodo initXlet() restituisce il valore di ritorno, l’application manager invoca il metodo startXlet() e l’applicazione passa dallo sto Paused a Started ed è pronta per interagire con l’utente. L’applicazione a questo punto può passare negli stati Paused e Started invocando i metodi opportuni. Alla fine del suo ciclo di vita l’applicazione passa nello stato destroyed tramite il metodo destroyXlet() e l’applicazione libera le risorse. 20 2.1.2 Profili Lo standard MHP si caratterizza per due livelli evolutivi di specifiche. L’ MHP 1.0.x definisce i primi due profili, l’enhanced broadcast e interactive broadcast. L MHP 1.1.x estende MHP 1.0 e aggiunge l’ultimo profilo l’internet access. Ad ogni profilo è associato una dotazione hardware specifica obbligatoria per ogni piattaforma. Altre possono considerarsi facoltative o raccomandate. Il profilo enhanced broadcast è caratterizzato da un formato delle immagini a 16:9, audio con qualità cd e più canali audio, una memoria e un data carousel con un ciclo di aggiornamento breve. Con il profilo interactive broadcast diventa necessario il canale di ritorno che prima era opzionale. Avviene quindi una interazione utente server tramite la rete internet, vengono quindi implementati meccanismi di autorizzazione e sicurezza. Con il profilo Internet Access si vorrebbe arrivare ad un accesso permanente alla rete con una convergenza tra le tecnologie informatiche e quelle televisive, utilizzando i protocolli di sicurezza della rete internet. Questo profilo è però ancora poco sviluppato. 2.2 Compact Disc (CD) Il Digital Video Compact Disc, comunemente abbreviato in Video CD, in sigla VCD, è uno standard di videoregistrazione su compact disc dedicato all'home video. In ambito commerciale, come formato per la vendita di film o altro tipo di materiale filmato, ha avuto in passato solo una timida diffusione, non arrivando mai a rappresentare un vero e proprio concorrente per lo standard VHS. Oggi è stato soppiantato completamente dal DVD-Video, ma sopravvive in ambito amatoriale come formato di registrazione di bassa qualità alternativo al DVD. In passato erano in vendita lettori appositamente dedicati alla riproduzione di Video CD. Oggi sono stati sostituiti completamente dai lettori di DVD-Video i quali sono normalmente anche compatibili con il Video CD. Oltre che su lettori appositamente dedicati, è possibile leggere i Video CD anche su computer dotati di lettore di CD o DVD (quasi sempre compatibili anche con i CD) e apposito software. Esistono tre versioni di Video cd. La versione 1.0 fu la prima versione del Video CD progettata da Philips e JVC nel 1992 e fu denominata inizialmente Karaoke CD, perché il suo scopo era quello di essere utilizzato nelle applicazioni del Karaoke, allora diffuso solamente sul mercato giapponese. In questa versione erano presenti solo alcune caratteristiche basilari di quello che diventerà il Video CD, come per esempio la distinzione di ogni canzone in tracce MPEG. Successivamente all'uscita del Karaoke CD, le due società decisero di migliorarne le caratteristiche visto il suo possibile sviluppo all'interno del mercato dell'home video. Nel 1993 uscì la versione 1.1, la prima denominata con il termine Video CD, poiché fu la prima che consentì di memorizzare filmati cinematografici su Compact Disc. Il formato utilizzato era l’mpeg program stream come contenitore video, mentre le tracce audio erano in formato cd musicale (MPEG-1 layer II). Successivamente all'uscita della versione 1.1, Sony e Matsushita entrarono nel VCD Consortium, al fine di migliorarne lo sviluppo. Frutto della loro partecipazione fu la versione 2.0, uscita nel 1995 la quale ha ripreso le specifiche dello standard 1.1 con alcune notevoli aggiunte. Infatti consente la lettura di segmenti MPEG, i quali sono immagini in formato MPEG still pictures accompagnate o meno da audio in formato MP2, presentando inoltre una maggior interattività con l'inserimento 21 del sistema Playback Controll (PBC). Quest’ultimo consente ricerche all'interno di ogni traccia video grazie alla presenza di un file indice. Il sistema PBC presenta alcuni vantaggi. Per esempio, permette di avere un ordine di visione delle tracce diverso dall'ordine in cui esse sono memorizzate sul disco, consentendo in questo modo di poter inserire filmati che occupano poco spazio prima di tutti gli altri e di vederli successivamente. La caratteristica più interessante del sistema PBC, però, è la possibilità di inserire menù e, come conseguenza, è possibile far scegliere all'utente sia le tracce video che egli vuole visualizzare sia i capitoli posti all'interno di un filmato, se quest'ultima caratteristica è stata attivata sul Video CD. I menù possono essere sia segmenti MPEG, con o senza sottofondo audio, sia filmati in MPEG-PS, ma non possiedono quelle caratteristiche interattive che godono, invece, i menù dei DVD. Un VideoCD non si discosta tanto dai CD Audio o dati che maneggiamo tutti i giorni. In un'unica sessione possiamo trovare, tra due traccie di apertura e chiusura (Lead IN e Lead OUT), tracce MPEG, tracce CD-DA (Compact Disc Digital Audio) e una speciale traccia per dati sul VideoCD stesso. Questa traccia e' usata per contenere informazioni riguardanti i dati del CD grazie ai quali può avvenire la riproduzione per i lettori VideoCD. Può contenere anche dati per il Karaoke (se il VideoCD e' stato realizzato per tale scopo) oppure l'applicativo o i vari menu per selezionare le diverse tracce. CARTELLA VCD MPEGAV CDDA SEGMENT KARAOKE EXT FILE Info.vcd Entries.vcd Psd.vcd Lot.vcd AVSEQnn.dat AUDIOnn.dat ITEMnnn.dat KARINFO.xxx PSD_X.vcd Lot_x.vcd Scandata.dat Captnn.dat SPIEGAZIONE Identificazione del disco e informazioni Lista Entry point Descrittore della sequenza di visualizzazione (opzionale) Lista Offset dei File (opzionale) File MPEG come video, extras, menu File Audio Oggetti da visualizzare, come immagini o menu Informazioni sul Karaoke (opzionale) Informazioni aggiuntive de PSD Informazioni aggiuntive de LOT Lista degli indirizzi degli I-Frames (indice) Tabella 2.1 Riassunto struttura VCD 22 Digital Versatile Disc (DVD) 2.3 Il DVD-Video è un'applicazione DVD riguardante tipi di dati multimediali audiovisivi suddivisi in file, organizzati secondo le specifiche proposte dal DVD Forum e sviluppate da OSTA (Optical Storage Technology Association). I dati video di questa applicazione sono compressi tipicamente utilizzando MPEG-2, mentre la compressione dei dati audio è variabile ed a scelta del produttore. Audio e video non sono memorizzati in file separati ma multiplexati in uno stream unico. Il file system del DVD è una variante ridotta dell'UDF (Universal Disc Format), chiamata MicroUDF. La struttura dei DVD-Video, cioè il modo in cui i files sono memorizzati ed organizzati all'interno del supporto di memorizzazione, è standard; questa organizzazione serve a fare in modo che tutti i riproduttori siano in grado di riprodurre senza problemi i dati. All'interno della radice vi sono due directory, chiamate AUDIO_TS e VIDEO_TS. Come i nomi suggeriscono, queste due directory sono deputate a contenere rispettivamente gli elementi dei DVD-Audio e dei DVD-Video. In quest’ ultimo, dunque, AUDIO_TS è sempre vuota; VIDEO_TS contiene invece tutti gli elementi interessati nella riproduzione del video. All'interno di VIDEO_TS vi sono tre tipi di file, identificati da tre differenti estensioni: - - IFO: contiene le informazioni sulla dislocazione di audio, video e sottotitoli, sulla suddivisione in capitoli del film e su ogni altro contenuto; è il descrittore della struttura del DVD-Video. VOB: sta per Video Object; è il contenuto multimediale vero e proprio, cioè è un file è in cui sono memorizzati l'audio e il video in forma multiplexata. BUP: è un backup del file .IFO. Oltre ad avere specifiche estensioni, i file presenti nella directory VIDEO_TS sono anche caratterizzati da una specifica nomenclatura. I nomi dei file possono iniziare per VIDEO_TS o VTS_ dove TS è l’acronimo di TitleSet. I file che cominciano per VIDEO_TS sono i primi ad essere letti e contengono le informazioni ed i contenuti riprodotti automaticamente quando il supporto viene inserito nel lettore (p.es. le informazioni di copyright e il menu principale del DVD). Gli altri file, che iniziano per VTS_, racchiudono tutte le altre informazioni e contenuti. Gli archivi .IFO contengono i riferimenti ai .VOB da caricare; un singolo file .IFO può gestire al massimo 10 file. Si avrà quindi la seguente struttura: ROOT |-AUDIO_TS |-VIDEO_TS |-VIDEO_TS.BUP |-VIDEO_TS.IFO |-VIDEO_TS.VOB |-VTS_xx_y.BUP |-VTS_xx_y.IFO |-VTS_xx_y.VOB 23 Passiamo ora ad analizzare la struttura di un file VOB, per capire quindi come inserire i vari menu e contenuti multimediali interattivi: VMGM VTSM Titleset Title Chapters Cells Audio Streams SubPictures Video Manager Menu detto anche root Menu, è il primo livello della struttura di un DVD video. Le informazioni di navigazione menu sono contenute nel file VIDEO_TS.IFO (e nella copia .BUP) mentre le informazioni audio/video sono contenute nel file VIDEO_TS.VOB. Il pulsante Title del telecomando riporta a questo livello del DVD. Video Titleset Menu. Al secondo livello della struttura di un DVD ci sono i titleset, ciascuno corredato dal proprio menu. Il menu è contenuto nel corrispondente file VTS_nn_0.IFO e nella copia di backup .BUP. Il pulsante Menu del telecomando riporta a questo livello del DVD. Tutti i file che compongono un determinato titleset hanno il nome che inizia con VTS_nn, dove non è il numero del titleset che varia da 01 a 99. Ogni DVD ha almeno un titleset. Ogni titleset contiene uno o più titoli. L'insieme dei titoli è suddiviso in uno o più oggetti video (file .VOB). Il primo oggetto video di un titleset è un file con nome VTS_nn_1.VOB. I titoli sono suddivisi in capitoli. I capitoli costituiscono i punti di ingresso al video (selezione scene). Quando il lettore raggiunge la fine di un capitolo, passa automaticamente al successivo. La cella è l'unità base di riproduzione video. Ogni cella è identificata da un ID numerico univoco. L'ordine in cui le celle sono visualizzate è stabilito da una Program Chain (PGC), questo consente la creazione di percorsi di visualizzazione differenziati per lo stesso insieme di celle. Questa struttura può essere utilizzata per varie opzioni di riproduzione, come selezione del parental level, selezione dell'angolo di ripresa, selezione della storia. Sotto immagini o sottotitoli: sono 4 bitmap colorate le quali sono caricate sopra lo stream video. Sono fatti in questo modo i bottoni nei menu di navigazione. Tabella 2.2 Struttura DVD-Video Il menu di navigazione di un DVD presenta delle limitazioni; infatti un menu di primo livello VMGM può passare solamente ad un altro menu VMGM, al primo menu VTSM di un titleset o all’inizio di un titleset. Un menu di secondo livello VTSM può passare ad un altro menu VTSM dello stesso titleset, ad un titolo o capitolo dello stesso titleset o al primo VMGM del disco. 24 Utilizzando il programma freeware vStrip, possiamo analizzare in dettaglio un file VOB: Found 0xBF = Private 2 [@LBA 0] Found VOB-ID: 01/CELL-ID: 01 [@LBA 0] Encountered encrypted sector, attempting key recovery [@LBA 1] Deduced key: 0xC00374C61C (2/2 vkey(s)) Found 0xE0 = Video 0 [PTS 0:00:00.290 @LBA 1] Width = 720 Height = 480 Aspect-ratio = [3] 16:9 display Frame-rate = [4] 29.97 (30000/1001) fps Found 0xBD = Private 1, sub 0x80 [PTS 0:00:00.224 @LBA 99] Found 0xBD = Private 1, sub 0x81 [PTS 0:00:00.224 @LBA 100] Found 0xBD = Private 1, sub 0x82 [PTS 0:00:00.224 @LBA 101] Found 0xBD = Private 1, sub 0x83 [PTS 0:00:00.224 @LBA 102] Found 0xBE = Padding [@LBA 117] Found 0xBD = Private 1, sub 0x20 [PTS 0:00:00.724 @LBA 169] Found 0xBD = Private 1, sub 0x21 [PTS 0:00:00.724 @LBA 170] Found VOB-ID: 02/CELL-ID: 01 [@LBA 378] In questo caso abbiamo un solo video ed ha sempre l'ID 0xE0. Il PTS è il Program Time Stamp e ci dice quando inizia il video rispetto all'inizio del file VOB. Si può anche vedere che la risoluzione è di 720x480 quindi si tratta di un DVD in formato NTSC (americano). Il numero di fotogrammi al secondo (frame rate) pari a 29.97 conferma questa deduzione. Il DAR (display aspect ratio = rapporto di aspetto dell'immagine N.d.T.) è 16:9. A seguire, si vedono quattro canali audio agli ID fra 0x80 e 0x83; questi canali sono tutti di tipo AC3 poiché hanno il codice 0xBD, i cui sottocanali sono i già citati 0x8x. Nel caso l'audio sia codificato in DTS esso avrà ID 0xBD 0x88 oppure 0xBD 0x89; se fosse PCM avrà ID 0xBD, con i canali aventi ID 0xAx, da 0xA0 fino a 0xA9. Infine, un eventuale audio MP2 avrebbe indirizzo 0xCx. Gli ultimi due stream 0x20 e 0x21 sono i sottotitoli, anch'essi appartenenti al flusso avente l'ID 0xBD. 25 2.4 Blu - Ray Disc La tecnologia Blu - Ray, oltre a garantire una qualità audio video in alta definizione, permette anche grazie alla grande capacità di memorizzare grandi quantità di dati su un unico supporto, di sviluppare menu interattivi e ulteriori applicazioni complesse. Tutto questo è reso possibile grazie ad un nuovo livello di interattività. Blu - Ray supporta principalmente due modelli di interattività: HDMV e il Blu - Ray Disc Java (BD-J). HDMV permette l’aggiunta di nuove caratteristiche rispetto per esempio ad un dvd. Con l’utilizzo di HDMV è possibile utilizzare il PIP (Picture in Picture), l’aggiunta di menu multi pagina usati per esempio per realizzare Pop-up oppure realizzare effetti grafici avanzati. Tutto questo permette di realizzare pulsanti con diverse funzionalità interattive. HDMV permette di creare menu sicuramente dalle caratteristiche più avanzate di quelle di un normale DVD, ma se si vogliono realizzare applicazione più complesse è necessario utilizzare BD-J Grazie alla tecnologia BD-J è possibile portare un menu sovrapposto al video, in modo per esempio da permettere al direttore di un film di commentare la scena che viene visualizzata in quell’istante. Inoltre è possibile scambiare informazioni tramite la rete internet e quindi eseguire il download di contenuti extra. Tutto questo ovviamente non è possibile in un DVD e nemmeno in un CD. Tutti i riproduttori Blu - Ray in commercio devono supportare la tecnologia BD-J, ma non tutti al momento supportano le caratteristiche avanzate come salvare dati su un hard disk o l’accesso ad internet. Le caratteristiche avanzate vengono chiamate “Bonus View”, mentre l’accesso alla rete internet “BD Live”. Attualmente solo la Playstation 3 supporta a pieno queste caratteristiche. Dal 31 ottobre del 2007 tutti i player devono supportare il “Bonu View”, mentre il “BD Live” rimane comunque opzionale. BD-J si basa sulla stessa tecnologia dell’MHP, discussa in precedenza. Una applicazione BD-J quindi è un Java Xlet che viene controllata dall’Application Manger del lettore Blu - Ray attraverso l’interfaccia Xlet. La Xlet quindi può essere nello stato di loaded, paused, started, destroyed. Una volta che una Xlet viene distrutta ovviamente vengono liberate tutte le risorse che occupava. Il concetto chiave del BD-J è il BD-J Object. Quest’ultimo non è niente altro che una Java Xlet che viene registrata presso l’Application Management Table(ATM). Ogni titolo del disco o il disco stesso possono avere associata una ATM. Almeno una applicazione all’ interno dell’ATM deve essere auto start; questa applicazione verrà quindi eseguita quando verrà scelto il titolo corrispondente. Ovviamente BD-J supporta una GUI grafica, in modo da garantire all’utente un’interazione usando per esempio un telecomando o meccanismi di puntamento. Considerando che BD-J si basa sulla tecnologia Java, è possibile quindi manipolare le immagini e il testo utilizzando le opportune librerie. Un aspetto molto importante da tenere in considerazione è la sicurezza e il meccanismo di autenticazione. L’ambiente BD-J utilizza il modello di sicurezza implementato in Java per autenticare applicazioni firmate e garantire all’applicazione i relativi permessi. Il file .JAR che contiene l’applicazione viene firmato; la firma è in relazione con il disco stesso attraverso il BD Copy Protection System. Ovviamente verranno caricate solamente le applicazioni autenticate. L’applicazione una volta autenticata potrà: 26 - Leggere e scrivere sull’hard disk locale. Usare la rete per connettersi ad un server specifico o per scaricare contenuti. Accedere al file system del disco blu – ray. Poter selezionare i diversi titoli del disco. Controllare altre applicazioni BD-J eventualmente in esecuzione. BD-J contiene il Java Network Package. Le applicazioni quindi possono utilizzare queste librerie per connettersi a internet. La connessione fisica può variare a seconda che si usi una rete ADSL, una linea telefonica o altre reti. A livello di rete comunque viene supportato il protocollo TCP/IP e per comunicare con il server può essere usato il protocollo HTTP. Grazie all’implementazione della sicurezza solamente le applicazioni autorizzate possono accedere a Internet e inoltre può essere ristretto l’uso al protocollo TCP/IP solo per connettersi a siti autorizzati. BD-J può inoltre memorizzare contenuti in memoria. Il salvataggio può essere di tipo Mandatory System Storage oppure Optional Local Storage. I dati salvati tramite System Storage vengono memorizzati tipicamente su memoria flash e riguardano per esempio i settaggi di una specifica applicazione. Questa caratteristica deve essere presente su tutti i player Blu - Ray. Il Local Storage invece riguarda soprattutto il salvataggio di contenuti audio video scaricati dalla rete e per questo motivo è necessario un Hard Disk. Si può accedere a tutti i dispositivi utilizzando il Java IO Package. Visto che i dati salvati sono condivisi da tutti i dischi che verranno utilizzati con il lettore, le applicazioni BD-J potranno accedere solo a settori specifici di memoria, cioè quelli assegnati ad un dato disco. Mentre in un DVD avevamo le sole cartelle VIDEO_TS e AUDIO_TS, le cartelle in cui verranno salvati dati all’interno di un Blu - Ray saranno invece le seguenti: ROOT |- BDMV |- PLAYLIST (lista file video come xxxxx.mpls) |- CLIPNIF (file di informazione sul clip (zzzzz.clpi) |- STREAM (file audio/video transport stream (zzzzz.m2ts) |- AUXDATA (dati audio e font per I sottotitoli) |- META (file dati per la libreria del disco o caratteristiche di ricerca) |- BDJO (BD-J Object Files) |- JAR (Java archive files for BD-J) |- BACKUP (copie di backup di dati) |-CERTIFICATE |- BDMV ID file e certificato di root per l’autenticazione con AACS |- BACKUP del file BDMV ID e del certificato di root 27 La struttura di un disco Blu - Ray sarà quindi la seguente: Index Table Tabella contenuti Menu principale First play Interfaccia utente HDMV Control HDMV Movie Object HDMV Movie Object BD-J Control BD-J Object BD-J Object PLAYLIST Play item Play item Play item Play item CLIPS (AV) CLIP AV STREAM AND BUTTON OBJECT CLIP A CLIP AV STREAM AND BUTTON OBJECT CLIP B Figura 2.3 Struttura disco Blu - Ray 28 3 Capitolo Tool 3.1 FFMPEG FFMPEG è un programma che può convertire, registrare creare stream video e audio digitali in numerosi formati. FFMPEG è un tool a linea di comando che è composto da una collezione di software free e librerie open source. Include infatti la libreria libavcodec, un codec audio video utilizzato anche in altri progetti, e libavformat, una libreria che consente il multiplexing e il de multiplexing di audio e video. Il nome del progetto deriva dal formato video standard MPEG, insieme a FF che sta per ‘Fast Forward’. Il progetto fu iniziato da Fabrice Bellard, mentre attualmente e mantenuto da Michael Niedermayer. Molti sviluppatori di FFMPEG fanno parte anche del progetto MPlayer. FFMPEG è sviluppato sotto piattaforma Linux ma può essere compilato anche in altri sistemi operativi come MAC-OS X o Windows. Durante il progetto FFMPEG sono stati creati due codec lossless: FFV1 e Snow Codec, entrambi ancora in fase di sviluppo. Il progetto è costituito da diversi componenti: - - ffmpeg: è un’applicazione a linea di comando per convertire un formato video in un altro, è anche in grado di acquisire flussi video direttamente da una scheda TV. ffserver: è un server per stream multimediali e supporta sia il protocollo HTTP e anche RTSP anche se quest’ultimo è ancora in fase di sviluppo. ffplay: è un semplice media player basato su Simple DirectMedia Layer (SDL) e sulle librerie di FFMPEG. libavcodec: è una libreria che contiene tutti i coder e decoder di FFMPEG. Molti codec sono stati sviluppati per garantire massime prestazioni e riusabilità. libavformat: è una libreria che contiene multiplexer e de multiplexer per i diversi formati contenitori. libavutil: è una libreria di aiuto che contiene routines comuni per diverse applicazioni di FFMPEG. Questa libreria include adler32 (algoritmo di checksum), crc, md5, sha1, il decompressore izo, cifratori e decifratori DES, AES, rc4 e un encoder decoder base64. libpostproc: è una libreria che contiene routines per postprocessare un video. libswscale: è una libreria che consente di realizzare lo scaling di un video. libavfilter: permette al video di essere modificato o esaminato tra il decoder e l’encoder. 29 VDR MPLAYER VDR SoftDevice FF Chip Xine VideoLan FFMPEG Figura 3.1 Diagramma di un possibile utilizzo di FFmpeg Il diagramma precedente mostra come è possibile utilizzare FFMPEG. VDR sta per Video Disk Recorder ed è un’applicazione Linux open source che consente ad un computer di funzionare come un digital video recorder, permettendo quindi di registrare qualsiasi programma tv su Hard Disk. Ovviamente sul computer deve essere presente una scheda TV. Xine è un motore in grado di riprodurre formati multimediali ed è stato sviluppato per sistemi linux. Xine utilizza per il suo funzionamento le librerie di FFMpeg o di altri progetti e permette anche la sincronizzazione dell’audio e del video in maniera manuale. 3.1.1 Simple DirectMedia Layer (SDL) SDL è un software open source multi piattaforma scritto in C che consente di fornire un astrazione delle varie piattaforme grafiche e delle varie API; in questo modo lo sviluppatore può scrivere applicazioni multimediali una sola volta ed eseguirle su diversi sistemi operativi come Linux Windows o MAC. La libreria è divisa in sottosistemi che riguardano per esempio l’audio e il video. Sono state implementate inoltre altre libreria che permettono funzionalità aggiuntive: - SDL_image – support per diversi formati immagine. SDL_mixer – funzioni audio complesse. SDL_net – supporto per la rete. SDL_ttf – support per il rendering dei font. SDL_rtf – support per il rendering di un semplice Rich Text Format. SDL ha al suo interno la parola layer perché è un contenitore di funzionalità del sistema operativo e fornisce tutte le funzionalità necessarie per accedervi. Per questo motivo SDL è diviso in moduli, e il sviluppatore potrà scegliere quello opportuno in base al sistema operativo utilizzato. 30 APPLICAZIONE LIBRERIA SDL DIRECT X WINDOWS framebuffer Xlib LINUX Figura 3.2 Esempio architettura SDL 3.1.2 Formati supportati Codec implementati all’interno del progetto originale: - Snow, FFV1 Codec supportati: - ATRAC3, H.261, H.263 e h.264/MPEG-4 AVC, Indeo 2 e 3, QDesign Music Codec 2, Smacker video, Sorenson 3, Theora ,Truespeech,TXD,VP5 e VP6, Vorbis, Windows Media Audio, WMV. Formati contenitori: - ASF,AVI,BFI,IFF, RL2, FLV, Matroska, Maxis XA, MSN Webcam stream, MPEG transport stream, TXD, OMA. 3.2 MEncoder e Mplayer MEncoder è un decoder video free a linea di comando. È un fratello stretto di MPlayer e può convertire tutti i formati supportati da MPlayer in una varietà di formati compressi e non compressi utilizzando diversi codec. Grazie ad Mencoder è possibile copiare un intero contenuto di uno stream audio e video direttamente su un file di output per evitare una possibile perdita di qualità causata per esempio dal re-encoding, permette di modificare solo l’audio o il video o di cambiare semplicemente il formato contenitore. Utilizzando MEncoder è possibile utilizzare anche una numerosa serie di filtri che permettono di trasformare uno stream audio video. È possibile 31 infatti aumentare o diminuire la luminosità o il contrasto, ruotare un immagine, modificare l’aspect ratio dei pixel di un video, cambiare lo spazio dei colori e ridurre il rumore. Mplayer è un media player open source e free. Il programma è distribuito per sistemi operativi linux ma anche per altri sistemi operativi. Mplayer supporta una vasta gamma di formati multimediali ed è anche in grado di salvare uno stream multimediale su file. Mencoder quindi può prendere in ingresso uno stream da Mplayer e convertirlo in diversi altri formati e utilizzare diversi filtri. La maggior parte dei codec video e audio sono supportati nativamente attraverso la libreria libavcodec del progetto FFMpeg. Mplayer può utilizzare perfino le dll di windows direttamente con l'aiuto di un caricatore DLL derivato dal progetto WINE. Lo sviluppo di MPlayer è incominciato nel 2000. All'autore originale Árpád Gereöffy si unirono in seguito altri programmatori dediti allo sviluppo del player. All'inizio la maggior parte degli sviluppatori venivano dall'Ungheria, ma oggigiorno gli sviluppatori provengono da tutto il mondo. Alex Beregszászi ha mantenuto MPlayer fino al 2003 quando Árpád Gereöffy lasciò lo sviluppo di MPlayer per iniziare un lavoro su una seconda generazione di MPlayer. Sfortunatamente il progetto MPlayer G2 fu in seguito abbandonato. Insieme a Mplayer viene fornito quindi Mencoder. Questo programma può prendere un file audio o video in uno dei formati disponibili e può ri-codificarlo in un altro formato, opzionalmente applicando al filmato trasformazioni geometriche o filtri audio o video durante il processo di codifica. 3.2.1 Formati supportati Formati contenitori: - 3GP, AVI, ASF, FLV, Matroska, MOV (QuickTime), MP4, NUT, Ogg, OGM, RealMedia Video Codec: - Cinepak, DV, H.263, H.264/MPEG-4 AVC, HuffYUV, Indeo, MJPEG, MPEG-1, MPEG-2, MPEG4 Part 2, RealVideo, Sorenson, Theora, WMV Codec Audio: - AAC, AC3, ALAC, AMR, FLAC, Intel Music Coder, Monkey's Audio, MP3, RealAudio, Shorten, Speex, Vorbis, WMA Sottotitoli: - AQTitle, ASS/SSA, CC, JACOsub, MicroDVD, MPsub, OGM, PJS, RT, Sami, SRT, SubViewer, VOBsub, VPlayer 32 3.3 Video Lan Video Lan è una soluzione software completa per lo streaming video. Il progetto fu fondato da studenti dell’università di Parigi e inseguito si aggiunsero sviluppatori di tutto il mondo. Il progetto Video Lan è open source. Video Lan è progettato per lo stream di video MPEG su reti a banda larga. Il progetto Video Lan è composto da due componenti: - VideoLan Server (VLS): funziona da server per stream di tipo MPEG, DVD, canali satellitari o terrestri digitali e video live con reti unicast o multicast. - VideoLan Client (VLC) : può essere utilizzando come client per riprodurre e decodificare diversi tipi di stream su diversi sistemi operativi. La maggior parte delle funzioni di VLS sono state però incorporate in VLC, formando il VLC media player. Di seguito viene riportato una schema che mostra un possibile utilizzo di VLC FILE VIDEO MAC DVD INTERNET Scheda di acquisizione Trasmissioni satellitari INPUT LINUX VLC/VLS WINDOWS Digitale terrestre PDA/MOBILE PHONE Figura 3.3 Utilizzo di VLC 33 VLC è un programma completamente modulare; in questo modo è molto semplice includere nuovi moduli per la lettura di nuovi formati, codec o metodi di streaming. In VLC attualmente ci sono più di 300 moduli. L’interfaccia grafica è basata su wxWidgest per Linux e Windows. Quest’ultima è un toolkit per creare interfacce grafiche per applicazioni multipiattaforma. Visto che VLC funziona anche da streaming server, può essere controllato anche da remoto utilizzando l’interfaccia opportuna. Ci sono anche interfacce che supportano telnet e http. VLC supporta tutti i codec e formati di file supportati da FFMPEG. Inoltre anche in VLC sono presenti diversi filtri che permettono di ruotare, dividere, distorcere o deinterlacciare uno stream audio video. Esistono diverse API che si possono connettere con VLC e usare le sue funzionalità: 3.3.1 libVLC API, il core di VLC, scritte in C,C++,C#. javascript API: evoluzione di API ActiveX e integrazione in Firefox. Interfaccia C#. Python. Java API. DirectShow filter. Formati supportati Input: - UDP/RTP unicast or multicast, HTTP, FTP, MMS, RTSP, DVDs, VCD, SVCD, CD Audio, DVB Formati contenitori: - 3GP, ASF, AVI, FLV, MKV, QuickTime, MP4, Ogg, OGM, WAV, MPEG-2 (ES, PS, TS, PVA, MP3), AIFF, Raw audio, Raw DV, MXF, VOB. Codec Video: - Cinepak, DV, H.263, H.264/MPEG-4 AVC, HuffYUV, Indeo 3, MJPEG, MPEG-1, MPEG-2, MPEG-4 Part 2, Sorenson ,Theora, VC-1, VP5, VP6, WMV. Sottotitoli: - DVD, SVCD, DVB, OGM, (partial)SubStation Alpha, SubRip, (partial)Advanced SubStation Alpha, MPEG-4 Timed Text, Text file, Vobsub, MPL2, Teletext. Codec Audio: - AAC, AC3, ALAC, AMR, DTS, DV Audio, XM, FLAC, MACE, MP3, PLS, QDM2/QDMC, RealAudio, Speex, Screamtracker 3/S3M, TTA, Vorbis, WavPack, WMA. 34 Output Formati contenitori: - ASF, AVI, FLV, MP4, Ogg, Wav, MPEG-2 (ES, PS, TS, PVA, MP3), MPJPEG, FLAC, MOV Codec Video: - H.263, H.264/MPEG-4 AVC, MJPEG, MPEG-1, MPEG-2, MPEG-4 Part 2, VP5, VP6, Theora, DV Codec Audio: - AAC, AC3, DV Audio, FLAC, MP3, Speex, Vorbis Protocolli di streaming: - UDP, HTTP, RTP, RTSP, MMS, File 3.3.2 Struttura modulare di VLC Il core di VLC Media Player è libVLC, che fornisce un interfaccia per le applicazioni per gestire le playlist, la decodifica dell’audio e del video, la gestione dell’output e tutti i thread di sistema. Tutti i file sorgenti di LibVLC sono situati nella directory src/ e in tutte le sue sotto directory: - config/: carica la configurazione da linea di comando e il file di configurazione, fornisce inoltre funzioni per i moduli per leggere e scrivere il file di configurazione. control/: funzioni per il controllo del comportamento di LibVLC, come Avvia/Pausa, gestione del volume, schermo intero, ecc.. extras/: contiene codice specifico per le diverse piattaforme. modules/: gestione dei moduli. network/: interfaccia di rete, gestione delle socie, errori della rete. osd/: gestione della visualizzazione di audio e video sullo schermo. test/: funzioni che devono essere testate. text/: gestione dei caratteri inteface/: contiene codice che gestisce l’interazione con l’utente, come la pressione di un tasto. playlist/: gestisce appunto la playlist. Input/: aprono un modulo di input, leggono i pacchetti, effettuano il parsing e passano gli stream elementari così ottenuti al decoder. video_output/: inizializza la visualizzazione del video, preleva le informazioni necessarie dal decoder come ad esempio i sottotitoli. audio_output: inizializza il mixer audio, infatti trova la giusta frequenza di riproduzione e ricampiona i frames audio ricevuti dal decoder. stream_output/: funzioni per eseguire lo streaming di audio e video su una rete. 35 - misc/: altre funzioni utilizzate in altre parti di LibVLC, come thread di sistema, rilevamento della CPU, le code dei messaggi, ecc.. L’idea alla base di LibVLC è la modularità. La libreria offre la possibilità di processare contenuti multimediali partendo dai diversi flussi che in ingresso come ad esempio un file o un stream , fino ad arrivare all’output come ad esempio un audio e video su un display o uno stream. Durante questo percorso le informazioni passano attraverso i vari decoder, filtri, demultiplexer e multiplexer. Lo schema seguente mostra la struttura dei moduli in VLC. Main (controllo programma) Interfaccia (gestisce i threads e l’utente) Inerfaccia (gestione e loop) Video_output Audio_output Video_output (rendering immagini e visualizzazione) audio_output (mixer frames audio e riproduttore) Vout_plugin (output driver) aout_plugin (output driver) Video_decoder Audio_decoder Video_decoder (decoder elementary stream) audio_decoder (decoder elementary stream) Intf_msg (output dei messaggi) Playlist (gestione playlist) Input Input (file oppure socket) Input_plugin (init,read,demux) Programs (gestione stream) Mpeg_system (demultiplexer) Clock (gestione temporale) Input_ext-inf (navigazione stream) Modulo di riferimento Crea,init,distrugge Gestione Fornisce informazioni Figura 3.4 Struttura modulare VLC 36 I moduli sono situati nella cartella moduli e in tutte le sottodirectory e vengono caricati a runtime. Ogni modulo può fornire differenti caratteristiche che meglio gestiscono un determinato file o un ambiente. I moduli vengono caricati dinamicamente attraverso le funzioni contenute nel file src/modules.c. VLC ha una struttura pesantemente multi-thread. Non può essere single-thread perché per esempio il decoder e l’output devono essere separati altrimenti non sarebbe garantita la corretta sincronizzazione dei frame. Ovviamente questo comporta un notevole aumento dell’overhead e una comunicazione pesante tra i vari processi. In VLC la decodifica e la visualizzazione sono asincrone. La decodifica viene eseguita tramite un thread per il decoder, la riproduzione invece da thread audio_output e video_output. Questo viene fatto per consentire la riproduzione dell’audio e del video nel giusto istante di tempo, senza bloccare il thread riferito al decoder. Questo comporta una complessa comunicazione tra interfaccia, input, decoder e output. Quando il programma VLC viene eseguito, il thread principale diventa il thread di interfaccia eseguendo i seguenti passaggi: - rilevamento CPU: Quale processore è utilizzato e le sue caratteristiche. inizializzazione interfaccia messaggi. parsing dei comandi da linea di comando. creazione playlist. inizializzazione moduli. apertura interfaccia. gestione segnali (SIGHUP, SIGINT, SIGQUIT). audio output. video output. ciclo principale: gestione degli eventi. La gestione dei messaggi è fondamentale; infatti la funzione printf() non è thread-safe. Una chiamata a questa funzione potrebbe lasciare il thread in uno stato indeterminato. È stata quindi realizzata una specifica API per stampare messaggi evitando crash. Esistono due modi per gestire questo problema: il primo è creare una coda dove i messaggi vengono inseriti e attraverso il ciclo del thread principale man mano il buffer viene svuotato. Nel secondo caso non è previsto nessun buffer ma il thread chiamante acquisisce un lock in scrittura e scrive il messaggio direttamente, evitando così due scritture contemporanee. All’avvio del programma VLC controlla tutti i plugin disponibili (nel caso di linux saranno file con estensione .so, per windows l’estensione sarà .dll). Ogni plugin viene settato con delle capacità specifiche attraverso la funzione set_capability(void* capability, int score). Le funzionalità disponibili sono le seguenti: 37 - interface access access_filter sout access : stream output sout stream audio filter video filter video filter2 audio mixer demux packetizer meta reader sout mux services_discovery chroma decoder audio output video output vizualisation packetizer Quando un thread avrà necessita di utilizzare un certo plugin, potrà scegliere il più opportuna tra quelli indicati per una data capacità. Le funzioni che vengono utilizzate da VLC per aprire, eseguire le varie operazioni e successivamente chiudere il modulo sono le seguenti: - Open ( vlc_object_t* p_object ) Run ( vlc_object_t* p_object ) Close ( vcl_object_t * p_object ) 38 4 Capitolo Analisi del problema e ambiente di Lavoro Il risultato che si vuole ottenere da questa tesi è quello di inserire all’interno di un transport stream il codice sorgente di un programma e multiplexare il tutto. Una volta fatto questo sarà necessario demultiplexare il transport stream, ottenere le informazioni del codice sorgente, compilare il programma e poi eseguirlo. Il formato contenitore transport stream è stato scelto per diversi motivi. Questo formato è stato scelto anche nel digitale terrestre e nelle trasmissioni via satellite per trasmettere contenuti audio video e dati. Per l’inserimento dei dati si può utilizzare il campo adaptation field (in particolare il transport_private_data), per inserire un file o un altro programma scritto in certo linguaggio all'interno di un transport packet. Il programma può anche essere inserito direttamente nel payload di un transport packet. Il transport stream inoltre offre la possibilità di aggiungere nuovi contenuti con una certa facilità. Per inserire dati all’interno del transport stream, in un primo momento la scelta era caduta su MHP e multiplexare quindi insieme all’audio e al video un DSM-CC object carousel in modo da consentire al ricevitore di eseguire l’applicazione. Il demultiplexer sarebbe stato realizzato utilizzando la libreria FFMPEG, in modo da gestire anche il flusso video MPEG-2. Questa idea è stata però scartata; il file system DSM-CC è molto complesso e il tutto sarebbe stato di difficile implementazione. Inoltre come flusso video è stato scelto al posto di MPEG-2 lo standard MPEG-4 part 10 (conosciuto anche come h264), che verrà analizzato successivamente. Per effettuare la codifica è stato utilizzato x264, una libreria software open source che consente appunto di codificare un flusso video in H264. Per poter gestire correttamente l'applicativo e sincronizzare il flusso audio video avevo pensato di utilizzare le API messe a disposizione dal Java Media Framework. Il problema del JMF è che supporta pochi formati. Per questo motivo avrei potuto utilizzare i codec e le librerie messe a disposizione da FFMPEG per risolvere il problema. Per chiamare direttamente il codice di FFMPEG avrei potuto utilizzare il Java Native Interface wrapper. Anche questa idea aveva però diversi problemi; infatti utilizzando Java l’applicativo creato sarebbe stato poco performante, inoltre la libreria FFMPEG non ha una gestione nativa completa del Transport Stream. L’attenzione così si è spostata su VLC. Inizialmente avevo preso in considerazione la versione 0.91. Quest’ultima, anche se ancora in fase di test, ha migliorato l’inserimento di un flusso video in h264 all’interno di un transport stream, ma avendo troppi problemi ancora irrisolti ho deciso di utilizzare la versione 0.86i che è sicuramente più stabile al momento. L’idea implementata che verrà analizzata in dettaglio in seguito è quella di sfruttare il flusso di sottotitoli per inserire il 39 sorgente del programma e di multiplexare quindi il flusso video in h264, l’audio e i sottotitoli modificati all’interno di un transport stream. In un secondo momento il transport stream è stato demultiplexato, estratte le informazioni dal flusso di sottotitoli, compilato il programma e poi eseguito. Come sistema operativo ho scelto Ubuntu versione 8.04.1; infatti quest’ultimo essendo una distribuzione Debian offre una maggiore flessibilità nella configurazione del sistema operativo e un maggiore supporto in rete. Dopo aver scaricato tutte le librerie necessarie, ho scaricato il codice sorgente di x264 utilizzando il git repository di videolan git clone git://git.videolan.org/x264.git Dopo averlo scaricato è stato compilato e installato utilizzando i seguenti comandi: ./configure && make && sudo make install Il commando ./configure controlla se sono presenti le librerie necessarie e permette opzionalmente di attivare o disattivare diverse azioni; il comando make compila tutti i sorgenti mentre il comando sudo make install installa l’applicazione in modalità utente root. Dopo aver installato x264, sono passato all’installazione di FFMPEG. Sebbene per realizzare l’applicazione è stato utilizzato VLC, la libreria FFMPEG viene utilizzata proprio da VLC per effettuare la codifica o la decodifica di alcuni flussi audio e video, tra i quali anche x264. I sorgenti sono stati scaricati utilizzando sempre git e i seguenti comandi: git clone git://git.mplayerhq.hu/ffmpeg/ cd ffmpeg git clone git://git.mplayerhq.hu/libswscale/ La compilazione è stata effettuata utilizzando un apposito comando di configurazione: ./configure --enable-liba52 --disable-debug --enable-libfaad -enable-libfaac --enable-gpl --enable-x264 --enable-xvid --enablepthreads --enable-libvorbis --enable-pp --enable-libtheora -enable-libogg --enable-libgsm --disable-swscaler --disable-debug -enable-shared Da notare soprattutto due opzioni: --enable-x264 consente ad FFMPEG di utilizzare le librerie x264 installate in precedenza, mentre –disable-swscaler è fondamentale disattivarla; infatti in caso contrario sarebbe impossibile compilare VLC. 40 A questo punto tutto è pronto per installare la versione 0.86i di VLC. I sorgenti sono stati scaricati dal sito di videolan: http://download.videolan.org/pub/vlc/0.8.6i/ Il comando di configure utilizzato è stato il seguente: ./configure --enable-st --enable-v4l --enable-faad --enabletwolame --enable-flac --enable-theora --enable-aa --enable-esd -enable-arts --enable-ncurses --enable-xosd --enable-slp --enablelivedotcom --enable-ffmpeg --enable-faad --with-ffmpeg-faac -with-ffmpeg-zlib --with-ffmpeg-mp3lame --with-ffmpeg-amrnb -enable-x264 --enable-mad --enable-wxwidgets --enable-skins2 -enable-dvdnav --enable-mostly-builtin --enable-sout --enable-shout --enable-vlm --enable-live555 --enable-dv --enable-dvdread -enable-dvbpsi --enable-dvb --enable-realrtsp --enable-real -enable-fb --enable-gnutls --enable-a52 --disable-zvbi --enabletelx. Poi come al solito sono stati lanciati i comandi: make && sudo make install Ora tutto è pronto per realizzare l’applicazione. 41 5 CAPITOLO Applicazione In questo capitolo andremo ad analizzare in dettaglio le parti realizzate in VLC per realizzare l’applicazione. Lo schema seguente riassume l’architettura dell’applicativo realizzato sia per multiplexare il transport stream ma anche per demultiplexarlo. VIDEO ENCODER X264 AUDIO ENCODER AUDIO FILE SORGENTE DEMUXER SOTTOTITOLI MULTIPLEXER TRANSPORT STREAM FILE.TS o STREAMING ENCODER SOTTOTITOLI Figura 5.1 Schema di realizzazione di un flusso transport stream DECODER X264 FILE.TS o STREAMING DEMULTIPLEXER TRANSPORT STREAM DECODER AUDIO RIPRODUZIONE AUDIO/VIDEO/ APPLICAZIONE DECODER SOTTOTITOLI Figura 5.2 Schema di realizzazione del multiplexer transport stream e della riproduzione a video Andremo ora ad analizzare passo per passo i vari componenti. 42 5.1 H.264/X.264 H.264 è uno standard per la compressione video. È anche conosciuto come MPEG-4 part 10 o come MPEG-4 AVC. La prima versione di questo standard è stata completata nel maggio del 2003. X264 è una libreria open source per realizzare la codifica H.264. Questo codec è obbligatorio per le specifiche HD-DVD e Blu - ray e ratificato nelle recenti versioni degli standard DVB (Digital Video Broadcasters) e 3GPP (3rd Generation Partnership Project). Numerose aziende nel settore broadcast, delle trasmissioni via cavo, del videoconferencing e dell’elettronica consumer stanno valutando l’uso di H.264 come codec video per i nuovi prodotti e servizi . L’intento del progetto era quello di creare uno standard capace di fornire una buona qualità video con sostanzialmente bitrates più bassi rispetto agli altri standard, senza aumentare la complessità e costi di implementazione. L’intento era anche quello di fornire una alta flessibilità in modo tale che lo standard si potesse applicare a diverse applicazioni, reti e sistemi. H.264 proprio per questo motivo è molto utilizzato anche nei video ad alta definizione, può essere incapsulato all’interno di un transport stream e quindi trasmesso o via satellite o digitale terrestre. Lo standard originale era conosciuto come Fidelity Range Extensions (FRExt) e non consentiva la codifica dei video in alta definizione. Col passare degli anni sono state introdotte diverse estensioni, come ad esempio la maggior precisione di campionamento dei bit e un alta risoluzione nell’informazione del colore che hanno consentito la codifica di video in hd. In un video assume molta importanza il legame che ha un immagine con la successiva; infatti molte parti della seconda immagine rimarranno immutate rispetto alla precedente. Proprio per questo motivo è possibile individuare le differenze tra le due immagini e creare quindi la seconda immagine a partire dalla prima in base alle parti che sono cambiate o spostate. Questo processo può essere visto come una stima del moto e richiede ovviamente meno bit rispetto alla trasmissione dell’immagine originale. Ovviamente questo processo non può essere applicato all’infinito; infatti i possibili errori di si accumulerebbero di passo in passo creando un risultato inconsistente. La predizione ovviamente non è vincolata ad andare solo avanti nel tempo, ma può essere applicata anche all’indietro. Le immagini che vengono codificate indipendentemente da tutte le altre vengono chiamate frame di tipo I (Intracoded), il blocco che consente di effettuare una predizione in avanti viene chiamato frame di tipo P (Predictive), mentre per realizzare la predizione all’indietro viene utilizzato un particolare tipo di frame chiamato B (Bidirectional). Il frame di tipo B ha un compressione maggiore rispetto al frame di tipo P, in quanto ha a disposizione due immagini come riferimento invece di una. Una delle caratteristiche principali di H.264 è la possibilità di utilizzare le immagini codificate in precedenza con una maggiore flessibilità rispetto ai codec precedenti, infatti può avere fino a 16 frame di riferimento oppure 32 nel caso di video interlacciato. Nei codec precedenti il numero di 43 frame di riferimento era tipicamente 1, oppure 2 nel caso dei B-Frame. Questo permette ovviamente una diminuzione della bit-rate e un miglioramento nella qualità della scena. H.264 ha inoltre una dimensione del blocco di codifica variabile in base alle caratteristiche dell’immagine da codificare. Si può passare infatti da un blocco 16x16 ad un blocco 4x4. Per stimare in maniera ottimale il movimento tra due frame possono essere utilizzati vettori di moto multipli per ciascun macroblocco. È anche possibile comprimere in maniera losless un singolo macroblocco; in questo modo il campione video viene visualizzato direttamente, consentendo una rappresentazione perfetta di una singola regione. Per effettuare la quantizzazione H.264 non utilizza la trasformata coseno discreta, ma utilizza una codifica arimetica di un blocco di dimensioni 4x4, ricollocando in maniera migliore i segnali residui e diminuendo quindi gli effetti di disturbo. Questa trasformata può essere eseguita anche su blocchi di dimensione 8x8. Il sistema di codifica prevede principalmente due livelli: 5.1.1 Video Coding Layer: rappresenta in maniera efficiente il contenuto video. Network abstraction layer: aggiunge un header opportune per il livello di trasporto o per il dispositivo di memorizzazione. Profili Di seguito vengono elencati i sette profili standard: - - Baseline Profile (BP): Principalmente per applicazioni a basso costo con limitate risorse computazionali, usato per videoconferenze o applicazioni per dispositivi mobili. Main Profile (MP): Originariamente era stato creato questo profilo come il principale per consentire lo streaming di contenuti multimediali, ma la sua importanza è venuta meno con lo sviluppo del profilo High. Extended Profile (XP). High Profile (HiP): Il profilo principale per lo streaming o il salvataggio su disco di contenuti multimediali in alta definizione. Questo è il profilo adottato anche per il Blu-Ray. High 10 Profile (Hi10P): aggiunge il supporto per più di 10 bit per campione della precisione dell’immagine codificata. High 4:2:2 Profile (Hi422P): utilizzato per applicazioni professionali. High 4:4:4 Predictive Profile (Hi444PP): supporta la codifica di ciascuna immagine separando i tre diversi piani colore. In aggiunta ai profili standard, sono stati inseriti altri profili per applicazioni standard: - High 10 Intra Profile. High 4:2:2 Intra Profile. High 4:4:4 Intra Profile. CAVLC 4:4:4 Intra Profile. 44 Oltre a questi profili, ne sono stati aggiunti altri tre detti profili scalabili per quelle applicazioni che necessitano appunto di scalabilità: 5.1.2 Scalable Baseline Profile:Principalmente utilizzato per videoconferenze e applicazioni per dispositivi mobili, si basa sul Baseline Profile. Scalable High Profile:Utilizzato per lo streaming di contenuti multimediali, si basa slu High profile. Scalable High Intra Profile: Per applicazioni professionali, si basa sugli Intra High Profile descritti in precedenza. Utilizzo di X.264 Per codificare un file video in H.264 utilizzando VLC, è necessario utilizzare la libreria FFMPEG che utilizza il codec X.264 installato proprio come descritto nel capitolo precedente. Possiamo vedere tutto ciò dal log di VLC: stream_out_transcode debug: creating video transcoding from fcc=`mp4v' to fcc=`h264' main debug: looking for decoder module: 20 candidates ffmpeg debug: libavcodec initialized (interface 3360000 ) ffmpeg debug: postprocessing disabled ffmpeg debug: using direct rendering ffmpeg debug: ffmpeg codec (MPEG-4 Video) started main debug: using decoder module "ffmpeg" main debug: looking for encoder module: 5 candidates x264 debug: version x264 0.60.X main debug: using encoder module "x264" Il comando quindi per codificare un flusso video in H.264 utilizzando X.264 e incapsularlo all’interno di un transport stream è il seguente: :sout=#transcode{vcodec=h264,vb=1024,scale=1,acodec=mp4a,ab=192,channels=2}:duplicate{dst =std{access=udp,mux=ts,dst=127.0.0.1:1234}} :sout-all Come si può notare l’audio in questo caso verrà codificato nel formato mp4a. 45 5.2 File sorgente e il problema dei sottotitoli Per inserire dei sottotitoli all’interno di un transport stream ci sono due possibilità. La prima è quella di ricodificare il flusso video imprimendogli i sottotitoli all’interno. Una volta fatto questo si dovrebbe multiplexare il flusso video e audio all’interno di un transport stream. Procedendo in questo modo però sarebbe impossibile una volta demultiplexato il transport stream, riottenere il flusso di sottotitoli separato dal flusso video. Proprio per questo motivo è necessario ragionare in modo completamente diverso. L’idea è quella di multiplexare un flusso video, un flusso audio e un flusso video separato all’interno di un transport stream in modo poi da poter estrarre le informazioni. Per fare questo VLC mette a disposizione un modulo opportuno: /modules/demux/subtitle.c Il compito quindi di questo file è quello di prendere in ingresso un file di sottotitoli, effettuarne il parsing e sincronizzarlo con i frame video. Andiamo a vedere più in dettaglio questo modulo. Il modulo viene inizializzato nel seguente modo: vlc_module_begin(); set_shortname( _("Subtitles")); set_description( _("Text subtitles parser") ); set_capability( "demux2", 0 ); set_category( CAT_INPUT ); set_subcategory( SUBCAT_INPUT_DEMUX ); add_float( "sub-fps", 0.0, NULL, N_("Frames per second"), SUB_FPS_LONGTEXT, VLC_TRUE ); add_integer( "sub-delay", 0, NULL, N_("Subtitles delay"), SUB_DELAY_LONGTEXT, VLC_TRUE ); add_string( "sub-type", "auto", NULL, N_("Subtitles format"), SUB_TYPE_LONGTEXT, VLC_TRUE ); change_string_list( ppsz_sub_type, 0, 0 ); set_callbacks( Open, Close ); add_shortcut( "subtitle" ); vlc_module_end(); Grazie alle funzioni set_capability(), set_category, set_subcategory(), quando viene passato a VLC un file di sottotitoli, questo viene catturato da questo modulo e ne viene effettuato il demultiplexaggio. Nell’inizializzazione vengono anche definiti tutti gli eventuali parametri da poter passare al modulo. Come si può notare dalla set_callback(), le due funzioni che si possono chiamare sono la Open e la Close che ovviamente eseguono le procedure di apertura e di chiusura. È importante capire correttamente la funzione Open per lo scopo che vogliamo raggiungere. 46 static int Open ( vlc_object_t *p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; es_format_t fmt; . . . . . . p_demux->pf_demux = Demux; p_demux->pf_control = Control; p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); p_sys->psz_header = NULL; p_sys->i_subtitle = 0; p_sys->i_subtitles = 0; p_sys->subtitle = NULL; p_sys->i_microsecperframe = 0; p_sys->i_original_mspf = 0; In questo modo viene definito quale parte del programma si occuperà di effettuare il demultiplex. Inoltre viene inizializzata la struttura demux_sys_t; quest’ultima è fondamentale perché cattura il flusso di sottotitoli in ingresso e agendo su quest’ultima si potranno fare le operazioni necessarie per gestire la sincronizzazione e i sottotitoli. Per il risultato che vogliamo ottenere, calcolare i fps (frame per second) del flusso video non è importante. È importante invece come questo modulo cerca di rilevare il formato di sottotitoli in ingresso. if( p_sys->i_type == SUB_TYPE_UNKNOWN ) { int i_try; char *s = NULL; msg_Dbg( p_demux, "autodetecting subtitle format" ); for( i_try = 0; i_try < 256; i_try++ ) { int i_dummy; if( ( s = stream_ReadLine( p_demux->s ) ) == NULL ) break; if( strcasestr( s, "<SAMI>" ) ) { In pratica viene eseguita una ricerca automatica del formato dei sottotitoli andando semplicemente a verificare se un particolare tipo di stringa è presente all’interno del file passato in input. Una volta rilevato il formato corretto, viene chiamata una funzione che ne esegue il parsing e sincronizza il flusso di sottotitoli con il video. È proprio in questo punto che è possibile intervenire; infatti basterà far rilevare al modulo il formato che noi desideriamo e poi chiamare la funzione che invece di effettuare il parsing di un normale flusso di sottotitoli effettuerà il parsing di un codice sorgente di un programma. 47 else if( strstr( s, "sorgente" ) ) { p_sys->i_type = SUB_TYPE_SOURCE; break; } All’interno del nostro file sorgente è fondamentale quindi inserire come prima riga il commento //sorgente; in questo modo il file verrà riconosciuto come file sorgente e chiamata la funzione corretta per il parsing. Prima di analizzare la funzione che effettua il parsing del file sorgente è opportuno fare una considerazione sul fourcc (four character code). Questo è una sequenza di 4 byte usata per identificare in maniera univoca un particolare formato di dati. È fondamentale quindi settare il corretto fourcc per il nostro flusso di dati: if( p_sys->i_type == SUB_TYPE_SOURCE ) { es_format_Init( &fmt, SPU_ES, VLC_FOURCC( 's','u','b','t' ) ); } In questo modo il programma sorgente avrà come fourcc ‘subt’; il decoder quindi lo riconoscerà come flusso di sottotitoli standard e creerà quindi un opportuno header ed un opportuno payload per questo tipo di dato. 5.3 Il parsing Un possibile esempio di sorgente di un programma che è possibile inserire all’interno di un transport stream è il seguente: //sorgente #include "stdio.h" int main(){ int p; scanf("%d",&p); printf("%d\n",p); return 0;} //fine La funzione creata che effettua il parsing è quindi la seguente: static int ParseAppSource( demux_t *p_demux, subtitle_t *p_subtitle) { demux_sys_t *p_sys = p_demux->p_sys; text_t *txt = &p_sys->txt; char *psz_text; 48 p_subtitle->i_start = 0; p_subtitle->i_stop = 0; p_subtitle->psz_text = NULL; char buf[100000]; FILE * pFile; pFile = fopen("/filesrc.txt","a"); int i_start; int i_stop; for( ;; ) { char *s = TextGetLine( txt ); if( !s ) { return VLC_EGENERIC; } psz_text = strdup( s ); if( !psz_text ) { return VLC_ENOMEM; } if( strcmp( psz_text,"//sorgente" ) == 0 ) { p_subtitle->i_start = 20000000; p_subtitle->i_stop = 25000000; p_subtitle->psz_text = "//sorgente"; return 0; } if( strcmp( psz_text,"//fine" ) == 0 ) { i_start = 40000000; i_stop = 45000000; break; } strncat(buf,psz_text,80); strncat(buf,"\n",1); free(psz_text); } fprintf(pFile,"%s",buf); fclose(pFile); p_subtitle->i_start = i_start; p_subtitle->i_stop = i_stop; 49 p_subtitle->psz_text = buf; //free( buf ); return ( 0 ); } Analizziamo come prima cosa la struttura p_subtitle. Grazie al campo i_start e i_stop è possibile settare l’istante di inizio di visualizzazione del sottotitolo e l’istante finale di visualizzazione. Il campo psz_text invece permette di settare il testo del sottotitolo. Questa funzione in pratica legge riga per riga il testo sorgente, lo salva in ‘buf’ e questo sarà il nostro file sorgente che verrà camuffato da sottotitolo. Come prova di correttezza il file letto viene salvato anche su un file di testo. È necessario quindi nel file che vogliamo inserire mettere come ultima riga il commento “//fine”, in questo modo la funzione esce dal ciclo for() infinito. Purtroppo sia nella versione 0.86i sia nella nuova 0.9x, il decoder che viene utilizzato per visualizzare i sottotitoli ha diversi problemi e in pratica viene sempre saltato il primo sottotitolo. Per poter estrarre poi le informazioni come verrà spiegato inseguito, è stato necessario inserire un falso sottotitolo. A tal proposito è tornato utile il commento “//sorgente”. Se si fa la differenza di i_stop – i_start si ha ovviamente la durata di visualizzazione a video del sottotitolo. Nell’esempio sopra il sorgente del programma verrebbe visualizzato per circa 5 secondi; se ovviamente si riduce questo intervallo il sorgente verrebbe visualizzato solamente per qualche millesimo di secondo rendendolo impercettibile all’occhio umano. Modificando i parametri di i_start e i_stop è anche possibile decidere in quale istante l’applicazione verrà poi eseguita. Il comando di VLC per inserire quindi all’interno di un transport stream un programma sorgente, un flusso video in h.264 e un flusso audio è il seguente: :sout=#transcode{vcodec=h264,vb=1024,scale=1,acodec=mp4a,ab=192,ch annels=2,scodec=dvbs}:duplicate{dst=std{access=udp,mux=ts,dst=127. 0.0.1:1234}} :sout-all Inserendo nella transcodifica l’opzione scodec=dvbs, verrà inizializzato l’encoder dei sottotitoli che si occuperà di creare il flusso nella maniera corretta in base al fourcc in questione. Come si può notare dal log di VLC il file sorgente viene caricato nella maniera corretta: main debug: using access2 module "access_file" main debug: pre-buffering... main debug: received first data for our buffer main debug: creating demux: access='' demux='subtitle' path='/home/bonj/Scrivania/Test/file2.c' main debug: looking for demux2 module: 2 candidates vobsub debug: this doesn't seem to be a vobsub file 50 subtitle debug: Movie fps: 23.976000 subtitle debug: autodetecting subtitle format subtitle debug: detected AppSource format subtitle debug: loading all subtitles... subtitle debug: loaded 2 subtitles main debug: using demux2 module "subtitle" 51 5.4 L’Encoder dei sottotitoli La codifica dei sottotitoli viene eseguita dal modulo modules/codec/dvbsub.c. Questo modulo esegue sia la codifica che la decodifica dei sottotitoli. Al momento verrà analizzata solamente la parte di codifica. L’encoder dei sottotitoli viene inizializzato dalla funzione OpenEncoder ed il fourcc che viene restituito per il flusso di sottotitoli è “dvbs”. Questo fourcc verrà riconosciuto dal multiplexer transport stream e potrà così assegnarli il pid opportuno e una struttura corretta. All’interno di un transport stream possono essere inseriti sottotitoli solamente del tipo “dvbs” e “telx”. Nell’inizializzazione dell’encoder si può notare come venga definito il fourcc “dvbs”. static int OpenEncoder( vlc_object_t *p_this ) { encoder_t *p_enc = (encoder_t *)p_this; encoder_sys_t *p_sys; . . . . . . . . . . p_enc->p_sys = p_sys; p_enc->pf_encode_sub = Encode; p_enc->fmt_out.i_codec = VLC_FOURCC('d','v','b','s'); La funzione di encode costruirà poi il pacchetto di sottotitoli corretto: bs_write( s, 8, 0x20 ); /* Data identifier */ bs_write( s, 8, 0x0 ); /* Subtitle stream id */ encode_page_composition( p_enc, s, p_subpic ); encode_region_composition( p_enc, s, p_subpic ); encode_clut( p_enc, s, p_subpic ); encode_object( p_enc, s, p_subpic ); /* End of display */ bs_write( s, 8, 0x0f ); /* Sync byte */ bs_write( s, 8, DVBSUB_ST_ENDOFDISPLAY ); /* Segment type */ bs_write( s, 16, 1 ); /* Page id */ bs_write( s, 16, 0 ); /* Segment length */ bs_write( s, 8, 0xff );/* End marker */ In questo modo verrà costruito il pacchetto correttamente che verrà poi decodificato dalla funzione decoder sempre utilizzando il file dvbsub.c. Se al file sorgente che è stato inserito fosse stato dato un fourcc diverso da “subt”, la funzione encoder non sarebbe stata in grado di costruire il pacchetto correttamente e di conseguenza il decoder non avrebbe restituito nessuna informazione. 52 5.5 Transport Stream Multiplexer e Demultiplexer Arrivati a questo punto tutto è pronto affinché i vari flussi vengano multiplexati e venga creato un transport stream. Il modulo che esegue questo è module/mux/mpeg/ts.c. Il multiplexer non fa altro che prendere in ingresso ogni singolo flusso, assegnargli un PID opportuno e creare un unico flusso transport stream. Il TS creato può essere mandato in streaming oppure salvato su file. Se analizziamo il file di log generato dopo la creazione del transport stream si può osservare come vengano assegnati i vari PID ai vari flussi: main debug: using audio filter2 module "audio_format" stream_out_duplicate debug: duplicated a new stream codec=mp4a (es=1 group=0) mux_ts debug: adding input codec=mp4a pid=68 mux_ts debug: new PCR PID is 68 stream_out_duplicate debug: - added for output 0 mpeg_audio debug: MPGA channels:2 samplerate:48000 bitrate:160 main debug: adding a new input stream_out_transcode debug: creating video transcoding fcc=`mp4v' to fcc=`h264' main debug: looking for decoder module: 20 candidates mux_ts debug: adding input codec=h264 pid=69 mux_ts debug: new PCR PID is 69 stream_out_duplicate debug: - added for output 0 from stream_out_transcode debug: creating subtitles transcoding from fcc=`subt' to fcc=`dvbs' main debug: looking for encoder module: 5 candidates main debug: using encoder module "dvbsub" stream_out_duplicate debug: duplicated a new stream codec=dvbs (es=2 group=0) main debug: adding a new input mux_ts debug: adding input codec=dvbs pid=70 stream_out_duplicate debug: - added for output 0 Il demultiplexer, una volta ricevuto in ingresso il flusso transport stream, analizzerà la tabella PMT memorizzando tutti i PID relativi ai vari flussi. Ad ogni transport packet ricevuto il demultiplexer ricostruirà i flussi video, audio e sottotitoli in base ai PID dei vari pacchetti. 53 5.6 Il decoder di sottotitoli Una volta che il demultiplexer transport stream ha separato i flussi, entrano in esecuzione i vari decoder. Il decoder X.264 entrerà in esecuzione, così come quello audio, per riprodurre correttamente i flussi audio e video. Il modulo importante da analizzare è invece sempre il modules/codec/dvbsub.c. Questa volta non verrà presa in considerazione la parte che effettua la codifica, ma quella parte che si occupa di estrarre le informazioni dal flusso di sottotitoli. Il modulo viene inizializzato in maniera analoga a quello dei sottotitoli, solamente che in questo caso vengono settate le opzioni per funzionare da decoder: vlc_module_begin(); # define DVBSUB_CFG_PREFIX "dvbsub-" set_description( _("DVB subtitles decoder") ); set_capability( "decoder", 50 ); set_category( CAT_INPUT ); set_subcategory( SUBCAT_INPUT_SCODEC ); set_callbacks( Open, Close ); . . . . . . . . Dopo che il modulo è stato caricato e inizializzato correttamente, si passa alla fase di decodifica. In questa fase viene analizzato il pacchetto che arriva del flusso di sottotitoli, controllando che il tutto sia stato creato correttamente, come descritto nel precedente paragrafo. decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block; subpicture_t *p_spu = NULL; . . . . . . bs_init( &p_sys->bs, p_block->p_buffer, p_block->i_buffer ); if( bs_read( &p_sys->bs, 8 ) != 0x20 ) /* Data identifier */ { msg_Dbg( p_dec, "invalid data identifier" ); block_Release( p_block ); return NULL; } if( bs_read( &p_sys->bs, 8 ) ) /* Subtitle stream id */ { msg_Dbg( p_dec, "invalid subtitle stream id" ); block_Release( p_block ); return NULL; 54 } p_sys->b_page = VLC_FALSE; while( bs_show( &p_sys->bs, 8 ) == 0x0f ) /* Sync byte */ { decode_segment( p_dec, &p_sys->bs ); } if( bs_read( &p_sys->bs, 8 ) != 0xff ) /* End marker */ { msg_Warn( p_dec, "end marker not found (corrupted subtitle ?)" ); block_Release( p_block ); return NULL; } Dopo che sono state dichiarate le strutture opportune da utilizzare, viene come prima cosa caricato il flusso di sottotitoli tramite la funzione bs_init(),inserendo i vari pacchetti nel campo p_sys->bs. Viene poi controllato il “data identifier” del pacchetto del flusso di sottotitoli, poi viene controllato il “subtitle stream id”. Successivamente viene individuato il punto in cui deve essere visualizzato il sottotitolo e viene chiamata la funzione di decodifica vera e propria. L’ultimo controllo verifica se il pacchetto è stato terminato correttamente. 5.6.1 La decodifica del flusso Arrivati a questo punto è necessario capire non tanto come il sottotitolo viene visualizzato a video; il nostro scopo infatti è quello di estrarre il programma sorgente precedentemente inserito, salvarlo su file, compilarlo ed eseguirlo. La funzione che svolge questo compito è la decode_object(): static void decode_object( decoder_t *p_dec, bs_t *s ) { decoder_sys_t *p_sys = p_dec->p_sys; dvbsub_region_t *p_region; int i_segment_length, i_coding_method, i_version, i_id, i; vlc_bool_t b_non_modify_color; //sync_byte, segment_type processed. i_segment_length = bs_read( i_id = bs_read( i_version = bs_read( i_coding_method = bs_read( . . . and s, s, s, s, page_id have already been 16 ); 16 ); 4 ); 2 ); 55 . . . b_non_modify_color = bs_read( s, 1 ); bs_skip( s, 1 ); /* Reserved */ Come si può notare vengono lette dal pacchetto le altre informazioni utili. Dopo aver eseguito una serie di controlli per verificare se tutto è corretto, si passa finalmente all’estrazione del flusso: { FILE * pFile; pFile = fopen("file.txt","a"); /* DVB subtitling as characters */ int i_number_of_codes = bs_read( s, 8 ); uint8_t* p_start = s->p_start + bs_pos( s ) / 8; . . . . . . for( p_region = p_sys->p_regions; p_region != NULL; p_region = p_region->p_next ) { for( i = 0; i < p_region->i_object_defs; i++ ) { int j; if( p_region->p_object_defs[i].i_id != i_id ) continue; p_region->p_object_defs[i].psz_text = realloc( p_region->p_object_defs[i].psz_text, i_number_of_codes + 1 ); for( j = 0; j < i_number_of_codes; j++ ) { p_region->p_object_defs[i].psz_text[j] =(char)(bs_read( s, 16 ) & 0xFF); } p_region->p_object_defs[i].psz_text[j] = 0; fprintf(pFile,"%s",p_region->p_object_defs[i].psz_text); } } fclose(pFile); } A questo punto viene aperto un nuovo file, e carattere per carattere il flusso di sottotitoli viene salvato su un file di testo. In realtà quello che viene salvato all’interno del file è proprio il programma sorgente precedentemente inserito; questo file ora è pronto per essere compilato ed eseguito. 56 Per effettuare la compilazione e l’esecuzione, è stato utilizzata la funzione exec() della libreria unistd.h Il problema della exec è che una volta eseguita, restituisce un valore di ritorno solamente in caso di errore, altrimenti le righe di codice successive alla exec() non vengono eseguite. Per questo motivo l’idea è stata quella di creare due processi figli tramite l’uso della funzione fork(). Il primo si occuperà di compilare il programma, il secondo di eseguirlo. if(( pid1 = fork()) == 0) { Char *cmd[] = { "gcc", /home/bonj/Scrivania/filediprova.c", "-o", "file", (char *)0 }; execvp ("gcc", cmd); } else { if(( pid2 = fork()) == 0) { execvp("./file",NULL); perror("Error execute file"); } } Il primo processo figlio lancia quindi il compilatore gcc che compila il programma, il secondo invece lo esegue. La seconda execvp(), visto che cerca di eseguire un file binario, potrebbe avere problemi di permessi e non riuscire ad eseguire il file. In questo caso è necessario sostituire la execvp() con la funzione execve(). Attraverso questa funzione a differenza della precedente è possibile settare l’ambiente di esecuzione del programma, ottenendo quindi i permessi necessari all’esecuzione. Il comando sarebbe quindi il seguente: char *env[] = { "USER=bonj", "PATH=/usr/bin:/bin:/opt/bin", (char *) 0 }; execve("file", NULL, env); In questo modo durante la riproduzione del video, viene avviata l’applicazione nell’istante che era stato settato all’interno del file subtitle.c. 57 Conclusioni Questa tesi mi è servita per comprendere al meglio le caratteristiche dei vari formati contenitori, le loro limitazioni e come utilizzarli. Nello sviluppo dell’applicazione ho capito quanto sia diventata importante l’interattività nei vari ambiti; infatti sia che si parli di Blu-Ray o di digitale terrestre, la ricerca e lo sviluppo stanno andando proprio in questa direzione. L’applicazione da me realizzata potrebbe essere migliorata fornendo una compatibilità con altri sistemi operativi oltre a linux. Sono state utilizzate infatti funzioni e librerie tipiche di questo sistema operativo che non potrebbero funzionare per esempio in ambiente windows. Si potrebbe inoltre implementare una funzione che riconosca in maniera automatica il linguaggio in cui il programma sorgente è stato scritto, evitando quindi possibili problemi di compilazione dell’applicazione. La versione da me utilizzata di VLC per l’implementazione è la 0.86i. La comunità di VLC però è in pieno sviluppo e in futuro si potrebbe pensare di adattare il codice alle nuove versioni, risolvendo anche alcuni problemi relativi al decodificatore dei sottotitoli. 58 Bibliografia Gianluca Mazzini – Chiara Taddia Comunicazioni Multimediali Pitagora Editrice http://en.wikipedia.org/wiki/Comparison_of_container_formats http://en.wikipedia.org/wiki/Container_format_(digital) - avi: (AVI RIFF di Microsoft) http://msdn.microsoft.com/en-us/library/ms779636.aspx http://pvdtools.sourceforge.net/aviformat.txt (reference AVI 2.0 OpenDML) http://www.the-labs.com/Video/odmlff2-avidef.pdf - ogg: RFC3533 http://tools.ietf.org/html/rfc3533 RFC3534 http://tools.ietf.org/html/rfc3534 http://www.xiph.org/ogg/doc/ http://wiki.xiph.org/index.php/Main_Page - TS: http://neuron2.net/library/mpeg2/iso13818-1.pdf http://www.ce.unipr.it/~petrolin/livestreamer/dvb%20e%20TS.htm http://en.wikipedia.org/wiki/MPEG_transport_stream http://www.chiariglione.org/mpeg/faq/mp2-sys/mp2-sys.htm#mp2-12 http://gauss.ffii.org/PatentView/EP1133862 (Patent US6460086) Method and apparatus for delivery of a bytecode embedded within a transport stream 59 - Video CD: http://en.wikipedia.org/wiki/Video_cd http://www.ip.philips.com/view_attachment/2450/sl00812.pdf http://www.videohelp.com/vcd - Dvd Video: http://en.wikipedia.org/wiki/Dvd_video http://dvd.sourceforge.net/dvdinfo/index.html http://www.rigacci.org/wiki/doku.php/doc/appunti/linux/video/dvd_video http://www.doom9.it/dvd-structure.htm - Blu-Ray: http://en.wikipedia.org/wiki/Blu-ray_Disc http://www.videohelp.com/hd http://www.blu-raydisc.com/en/Technical/TechnicalWhitePapers/General.html http://www.blueboard.com/bluray/ (For BD-J) https://hdcookbook.dev.java.net/ - MHP: http://en.wikipedia.org/wiki/Multimedia_Home_Platform http://www.mhp-knowledgebase.org/ http://www.interactivetvweb.org/tutorials/mhp/xlet_introduction http://www.tvwithoutborders.com/tutorials http://www.mhp.org http://forums.java.net/jive/index.jspa 60 - VideoLan: http://www.videolan.org/ http://wiki.videolan.org/Main_Page http://www.videolan.org/doc/ http://forum.videolan.org/ http://www.videolan.org/developers/x264.html http://wiki.videolan.org/Developers_Corner ftp://ftp.videolan.org/pub/videolan/vlc/ (download last version of vlc for linux) - ffmpeg: http://ffmpeg.mplayerhq.hu/ http://wiki.multimedia.cx/index.php?title=Ffmpeg_codec_howto http://www.dranger.com/ffmpeg/ http://www.inb.uni-luebeck.de/~boehme/using_libavcodec.html http://www.divax.it/guide.asp?guida=Ffmpeg%20Reference - mencoder: http://www.mplayerhq.hu/design7/info.html#docs http://en.wikipedia.org/wiki/MEncoder http://gentoo-wiki.com/HOWTO_Mencoder_Introduction_Guide 61