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