Principiile Java Media Framework
JMF se bazeaza pe o arhitectura unificata si pe protocoale de management pentru administrarea proceselor de achizitie, procesare si transmisie a datelor media dependente de timp. JMF este conceput pentru a suporta majoritatea standardelor media cum ar fi: AIFF, AU, AVI, GSM, MIDI, MPEG, QuickTime, RMF si WAV.
Prin exploatarea avantajelor platformei JAVA, JMF respecta standardul "Scrie odata, ruleaza oriunde" ("Write Once, Run Anywhere TM"), el adresându-se programatorilor care doresc sa utilizeze audio si video în programele Java.
Cu JMF se pot crea usor applet-uri si aplicatii capabile sa prezinte, captureze, manipuleze si stocheze date media dependente de timp. Programatorii au posibilitatea de a procesa datele dupa voia lor, si de asemenea:
pot extinde JMF sa suporte formate aditionale;
pot modifica si optimiza formatele suportate;
pot crea mecanisme noi de prezentare.
8.3.1. Arhitectura de nivel înalt
Dispozitivele cum este VCR-ul (Video Cassete Recorder) sunt des întâlnite pentru realizarea operatiilor de înregistrare, procesare si prezentare a datelor media dependente de timp. Când se ruleaza un film folosind un VCR, stream-ul media provine de la caseta video. VCR-ul citeste si interpreteaza datele de pe caseta si trimite semnalul adecvat spre televizor si boxe.
În Figura 8.2 este prezentat acest proces de înregistrare procesare si prezentare
Figura 8.2. Procesul de înregistrare, procesare si prezentare
JMF se bazeaza pe acest model fundamental. Sursa datelor folosita în JMF încapsuleaza stream-ul media ca si caseta video despre care vorbeam mai devreme. Player-ul din JMF are aceleasi functii si mecanisme de control ca si un VCR. Rularea si captura audio si video din JMF necesita dispozitive de intrare si iesire similare, cum ar fi microfonul, camera, boxele si monitorul.
Sursele datelor si dispozitivele de rulare sunt parte integranta a arhitecturii API de înalt nivel a JMF. Aceasta arhitectura de nivel înalt se refera la componentele standard din JMF. Arhitectura JMF de nivel jos se refera la posibilitatea programatorului de a dezvolta sau extinde instrumente de lucru proprii. Aceasta arhitectura multistrat permite dezvoltatorilor de programe Java sa aiba la dispozitie un API usor de utilizat si de integrat în aplicatii Java, beneficiind în continuare de flexibilitatea si extensibilitatea necesara pentru crearea unor aplicatii media avansate si usor upgrade-abile.
8.3.1.1. Modelul Time (Timp)
JMF controleaza timpul cu o precizie de nanosecunde. Un anumit punct particular în timp este vazut în general ca un obiect Time, desi exista si câteva clase care suporta specificarea timpului în nanosecunde.
Clasele care suporta modelul de timp JMF implementeaza interfata Clock pentru a tine cont de 838f56i timpul necesar pentru o anumita operatie efectuata asupra unui stream media. Interfata Clock defineste operatiile de baza de cronometrare si sincronizare, care sunt necesare pentru a controla prezentarea media.
Figura 8.3. Modelul Time la Java Media Framework
Un Clock foloseste TimeBase pentru a contoriza trecerea timpului în timp ce un stream media este prezentat. Singura informatie pe care TimeBase o ofera este timpul curent, care poarta numele de time-base time. Acest timp nu poate fi oprit sau resetat. De obicei, timpul oferit de TimeBase se bazeaza pe ceasul sistemului, ora exacta fiind aflata de la BIOS-ul calculatorului.
Media time reprezinta pozitia curenta în cadrul unui stream media (începutul stream-ului este media time zero, sfârsitul stream-ului fiind maximul media time pentru acel stream). Durata stream-ului media este timpul scurs între start si stop, adica lungimea de timp necesara pentru prezentarea stream-ului media.
Pentru a cunoaste timpul curent, Clock foloseste:
timpul de start al bazei de timp - timpul pe care TimeBase îl raporteaza ca început al prezentarii;
timpul de start al datelor - pozitia din stream-ul media când prezentarea începe;
rata de playback - cât de rapid Clock-ul ruleaza fata de TimeBase. Rata este un factor scalar care se aplica la TimeBase. Spre exemplu, o rata de 1.0 reprezinta rata de playback normala pentru stream-ul media, în timp ce o rata de 2.0 indica ca prezentarea va rula de doua ori mai rapid decât rata normala. O rata negativa indica faptul ca Clock-ul ruleaza în directie opusa de TimeBase-ul lui (spre exemplu, se foloseste la derularea înapoi).
Când începe prezentarea, timpul media este mapat la timpul de baza si avansarea timpului de baza este folosita pentru a masura scurgerea timpului. În timpul prezentarii, timpul media curent este calculat folosind urmatoarea formula
MediaTime=MediaStartTime+Rate(TimeBaseTime-TimeBaseStartTime)
Când prezentarea se opreste, timpul media se opreste si el, dar timpul de baza media continua sa avanseze. Daca prezentarea este repornita, timpul media se remapeaza în functie de timpul media de baza curent.
8.3.1.2. Managerele
API-ul JMF consta în special din interfete care definesc comportarea si interactiunea obiectelor folosite pentru a captura, a procesa si prezenta date media dependente de timp. Prin folosirea unor interfete intermediare numite managere, JMF usureaza integrarea implementarilor interfetelor importante care pot fi folosite prin intercalarea cu clasele existente.
JMF foloseste patru managere:
Manager - Managerul general, trateaza construirea Player-elor, Procesoarelor, DataSources si DataSinks. Din perspectiva clientului, aceste obiecte sunt create întotdeauna prin aceleasi metode, indiferent daca obiectul este construit dintr-o implementare existenta sau una noua creata de utilizator;
PackageManager - Managerul de pachete, mentine un registru cu pachete ce contin clasele JMF, cum ar fi Player-ele, Procesoarele, DataSources si DataSinks;
CaptureDeviceManager - Managerul de dispozitive de captura, mentine un registru care contine toate dispozitivele de captura disponibile;
PlugInManager - Managerul de plug-in-uri, mentine un registru cu toate plug-in-urile de procesare JMF disponibile, cum ar fi Multiplexoarele, Demultiplexoarele, Codec-urile, Effect si Render.
Pentru a scrie programe bazate pe JMF, trebuie apelat la Managere pentru a crea metode pentru construirea Player elor, Procesoarelor, DataSource-lor si DataSink-urilor necesare aplicatiilor.
Daca se face captura de la un dispozitiv, se foloseste CaptureDeviceManager pentru a afla ce dispozitive sunt disponibile si pentru a accesa informatiile disponibile despre acestea. Daca se doreste si controlarea proceselor ce au loc asupra datelor, trebuie folosit PlugInManager-ul pentru a afla ce plug-in-uri au fost înregistrate.
Pentru a extinde functionalitatea JMF-ului prin implementarea unui plug-in nou, acesta trebuie înregistrat cu PlugInManager-ul pentru a-l face diponibil pentru Procesoare. Pentru a modifica un Player, un Procesor, DataSource sau DataSink, trebuie înregistrat prefixul package-ului din care face parte. Aceasta se face folosind PackageManager-ul.
8.3.1.3. Modelul Event (Eveniment)
JMF utilizeaza un mecanism structurat de raportare a evenimentelor pentru a informa programele despre starea curenta a sistemului media si pentru a le permite acestora sa raspunda erorilor aparute. Ori de câte ori un obiect JMF trebuie sa raporteze starea sa, el genereaza un MediaEvent. MediaEvent este alcatuit în asa fel încât sa poata clasa toate tipurile particulare de evenimente.
Pentru fiecare tip de obiect care poate genera un MediaEvent, JMF defineste o interfata de ascultare (listener) corespunzatoare.
Obiectele cu functii de control, cum sunt Player-ele sau Procesoarele genereaza evenimente media.
Figura 8.4. Modelul Event în JMF
8.3.1.4. Modelul Data (Date
Player-ele JMF folosesc de obicei DataSources pentru a administra transferul datelor de tip media. Un obiect DataSource încapsuleaza atât informatii despre locatia unde se afla sursa media cât si despre protocolul si software-ul care trebuie folosit pentru transferul datelor. Odata accesata, o sursa nu poate fi refolosita pentru a transfera alte date. Un obiect DataSource este identificat fie printr-un MediaLocator JMF fie printr-un URL (Universal Resource Locator). Un MediaLocator este similar unui URL si chiar poate fi construit dintr-un URL. El poate fi construit chiar daca protocolul corespunzator nu este instalat în sistem, spre deosebire de URL, care necesita existenta protocolului.
Un obiect DataSource adnimistreaza un set de obiecte SourceStream. O sursa standard foloseste o matrice de tip byte ca unitate de transfer. O sursa de date de tip Buffer foloseste un obiect tampon ca unitate de transfer. JMF defineste mai multe tipuri de obiecte DataSource.
Figura 8.5. Modelul Data din JMF
Datele pot fi obtinute dintr-o varietate de surse, cum ar fisiere locale sau din retea sau din transmisii în direct. Sursele de date pot fi categorizate dupa modul în care transferul este initiat:
surse de date de tip Pull: clientul initiaza transferul de date si controleaza fluxul datelor. Protocoalele folosite în acest caz sunt HTTP (Hypertext Transfer Protocol) si FILE. JMF defineste doua tipuri de surse de date de tip Pull: PullDataSource si PullBufferDataSource, care foloseste un buffer ca unitate de transfer;
surse de date de tip Push: server-ul initiaza transferul de date si controleaza fluxul datelor Acestea pot fi date de tip multicast, broadcast sau VOD (Video On Demand). Pentru datele de tip broadcast, un protocol folosit este Real-time Transport Protocol (RTP), protocol care a fost dezvoltat de catre Internet Engineering Task Force (IETF). Pentru VOD se foloseste protocolul MediaBase dezvoltat de catre SGI. JMF defineste doua tipuri de date de tip Push: PushDataSource si PushBufferDtaSource, care foloseste un obiect de tip Buffer ca unitate de transfer.
Gradul de control pe care îl are un program client depinde de tipul de date pe care le contine sursa. Spre exemplu, un fisier MPEG permite repozitionarea si deci un program client poate permite utilizatorului sa ruleze din nou sau sa ruleze dintr-o alta pozitie. Spre deosebire de acest caz, o transmisie de date de tip broadcast este sub controlul server-ului si nu permite modificari în rulare ca si în cazul anterior. Anumite protocoale VOD permit functii de control limitate.
JMF defineste doua tipuri de surse de date speciale, surse de date clonabile (cloneable) si surse de date combinate (merging
O sursa de date clonabila poate fi folosita pentru a crea diferite clone pentru surse de date de tipul Pull sau Push. Pentru a realiza aceasta operatie, trebuie apelata metoda Manager createCloneableDataSource În continuare toate operatiile se refera doar la clona. Obiectul original DataSource nu mai este folosit direct. Sursele de date clonabile implementeaza interfata SourceCloneable, care defineste o metoda createClone. Prin apelarea acestei metode se pot crea oricât de multe clone ale DataSource
Clonele nu trebuie sa aiba neaparat aceleasi proprietati ca si sursa originala. Aceste proprietati pot fi modificate dupa clonare. O sursa MergingDataSource poate fi folosita pentru a combina stream-urile din mai multe surse într-o singura sursa. Aceasta permite ca un set de surse de date sa poata fi administrat dintr-un singur punct de control - când connect, disconnect, start sau stop sunt apelate, apelarile se refera la sursele de date combinate.
Pentru a construi o sursa de date combinate, trebuie apelata metoda createMergingDataSource. Pentru a asigura reusita operatiunii, trebuie ca toate datele sa fie de acelasi tip. Spre exemplu, nu se pot combina date de tip Pull cu date de tip Push. Durata sursei combinate este egala cu durata maxima a obiectelor combinate.
Formatul exact al unui obiect este reprezentat de un obiect de tip Format. Formatul însusi nu contine informatii despre codare sau despre durata, ci doar descrie numele codarii si tipul de date necesare formatului.
JMF extinde Format pentru a defini formate audio si video specifice, dupa cum se poate vedea în Figura 8.6.
Figura 8.6. Formatul datelor în JMF
Un AudioFormat descrie atributele specifice unui format audio, ca rata (sample rate) sau numarul de canale. Un VideoFormat încapsuleaza informatii referitoare la datele video. Mai multe formate sunt derivate din VideoFormat pentru a descrie atributele formatelor video uzuale, incluzând:
IndexedColorFormat
RGBFormat
YUVFormat
JPEGFormat
H261Format
H263Format
Pentru a primi informatii despre schimbarile de format de la un Controller, trebuie implementata o interfata ControllerListener si urmarite evenimentele FormatChangeEvents.
8.3.1.5. Interfata Control
Interfata JMF Control prevede un mecanism pentru setarea si interogarea atributelor unui obiect. Un Control permite de obicei accesul la componenta interfetei utilizator corespondenta, ceea ce ajuta utilizatorul sa controleze atributele obiectului.
Orice obiect JMF care vrea sa permita acces la obiectele Control corespunzatoare lui trebuie sa aiba implementata interfata Controls. Aceasta interfata defineste metode pentru obtinerea obiectelor Control asociate.
JMF defineste interfetele Control standard din Figura 8.8. Interfata CachingControl permite afisarea si monitorizarea progresului încarcarii. Daca un Player sau un Processor poate raporta progresul încarcarii, el implementeaza aceasta interfata pentru ca bara de progres (progress bar) sa poata fi afisata utilizatorului.
Interfata GainControl permite ajustari ale volumului audio, cum ar fi setarea nivelului sau reducerea lui la zero (mute) la iesirea unui Player sau Processor
Figura 8.7. Interfata GainControl
Figura 8.8. Controalele din JMF
Obiectele DataSink si Multiplexer care citesc date de la o DataSource si le scriu într-un fisier pot implementa interfata StreamWriterControl. Acest Control permite utilizatorului sa limiteze marimea stream-ului care este creat.
Obiectele FramePositioningControl si FrameGrabbingControl exporta capabilitatile de lucru la nivel de cadru pentru Playere si Procesoare.
FramePositioningControl permite pozitionarea exacta la nivel de cadru într-un stream. FrameGrabbingControl permite extragerea unui cadru dintr-un flux video
Obiectele pot implementa interfata FormatControl pentru a permite accesul la Format. FormatControl permite de asemenea si metode pentru interogarea si setarea formatului.
Un TrackControl este un tip de FormatControl care permite controlarea proceselor efectuate de obiectul Processor asupra unei anumite piste de date. Cu aceasta metoda, se poate specifica ce conversii de format se aplica unei piste individuale. De asemenea, se pot selecta ce plug-in-uri Effect, Codec sau Render sunt folosite de Processor.
Doua controale, PortControl si MonitorControl permite controlul utilizatorului asupra procesului de captura. MonitorControl permite previzualizarea (preview) datelor în timp ce sunt capturate sau codate.
BufferControl permite utilizatorului sa controleze buffering-ul facut de un anumit obiect.
JMF defineste si câteva controale pentru codec-uri pentru a permite utilizatorului sa controleze codec-urile hardware si software folosite pentru codare/decodare:
BitRateControl - folosit pentru a afla informatii despre rata (în biti/sec) unui stream sau pentru a controla codarea lui;
FrameProcessingControl - folosit pentru specificarea parametrilor la nivel de cadru , ceea ce permite codec-ului sa execute un set minimal de operatii;
FrameRateControl - permite modificarea numarului de cadre/secunda;
H261Control - permite controlul asupra codec-ului H.261, folosit la transmisia de imagini statice;
H263Control - permite controlul asupra parametrilor codec-ului video H.263, inclusiv suport pentru vectori nerestrictionati, codare aritmetica si extensii de compensare a erorilor;
KeyFrameControl - permite specificarea intervalului dintre cadrele de baza;
MpegAudioControl - exporta capabilitatile codec-ului audio MPEG si permite selectarea parametrilor ;
QualityControl - permite specificarea preferintelor pentru calitatea procesarii si solicitarea procesorului. O valoare mai mare pentru calitatea bitilor rezultati duce la îmbunatatiria calitatii;
SilenceSuppressionControl - permite modificare parametrilor pentru codec-urile audio. Când este pe on, codorul audio nu trimite spre iesire nimic daca nu detecteaza nimic la intrare.
8.3.1.6. Componentele interfetei utilizator
Un Control poate permite accesul la o interfata de tipul Component. Pentru a afla interfata impicita pentru un anumit Control, trebuie apelata metoda getControlComponent. Aceasta metoda returneaza o componenta AWT care se poate include într-un applet sau în fereastra unei aplicatii
Un Controller permite de asemenea si acces la interfata utilizator Components. Spre exemplu, un Player permite accesul atât la componenta vizuala si la componenta panoului de control. Pentru a afla aceste componente trebuie apelate metodele getVisualComponent si getControlPanelComponent.
Daca nu se doreste folosirea componentelor de control implicite, este posibila dezvoltarea unor componente utilizator
8.3.1.7. Extensibilitatea
Programatorii avansati si furnizorii de tehnologii pot extinde functionalitatea JMF în doua moduri:
prin implementarea unor plug-in-uri utilizator care pot fi folosite în paralel cu cele standard;
prin implementarea directa a interfetelor Controller, Player, Processor, DataSource si DataSink.
Prin implementarea unui plug-in devine posibila extinderea capabilitatilor unui Processor fara a mai fi nevoie de implementarea proprietatilor pe care acesta le are deja. Odata ce un plug-in este înregistrat (registered) cu JMF, el poate fi selectat ca o optiune de procesare pentru orice Processor care suporta API-ul plug-in-ului respectiv.
Plug-in-urile JMF pot fi folosite la:
extinderea sau înlocuirea capabilitatii de procesare a unui Processor, prin selectarea unui plug-in individual care sa fie folosit;
accesul la date într-un anumit punct al fluxului. Spre exemplu, diferite plug-in-uri de efect pot fi folosite înainte si dupa procesarea datelor;
procesarea datelor în afara Player-ului sau Processor-ului. Spre exemplu, se poate folosi un plug-in Demultiplexer pentru a obtine piste audio individuale dintr-un stream media multiplexat, cu scopul de a le rula cu Java Sound.
În anumite situatii este nevoie de un grad mai mare de flexibilitate si control. În aceste cazuri, este necesara modificarea interfetelor Controller, Player, Processor, DataSource sau DataSink. Spre exemplu, daca avem un decoder hardware MPEG, este posibila implementarea unui Player care primeste date de la DataSource si foloseste decoderul pentru a realiza operatiile de analiza, decodare si redare, toate într-un singur pas. De asemenea, pot fi implementate Playere utilizator avansate cum ar fi Media Player-ul de la Microsoft, Real Player-ul de la Real Network sau Hot Media de la IBM.
8.3.2. Prezentarea
În JMF, procesul de prezentare este modelat de interfata Controller. Aceasta defineste starile de baza si mecanismul de control pentru un obiect care controleaza, prezinta sau captureaza date de tip media dependente de timp. El defineste fazele prin care trece un controler si pune la dispozitia utilizatorului un mecanism ce permite controlarea tranzitiilor între aceste faze.
O serie de operatii care trebuie efectuate înainte de a începe prezentarea sunt consumatoare de timp. Din acest motiv, JMF permite controlul programatic al acestora.
Un Controller genereaza o serie de MediaEvent-uri pentru a face posibil accesul la informatii referitoare la starea în care se afla. Pentru a primi evenimente de la un Controller cum este un Player, trebuie implementata interfata ControllerListener.
API-ul JMF defineste doua tipuri de controlere: Player-ele si Procesoarele. Acestea sunt construite pentru o sursa particulara de date si în general nu sunt refolosite pentru a prezenta alte date.
Figura 8.9 prezinta Controller-ele din JMF.
Figura 8.9. Controller-ele în JMF
8.3.2.1. Player ele
Un Player proceseaza un stream de date si le reda la un anumit timp . O sursa de date este folosita pentru a asigura acest stream Player-ului. Destinatia unde se realizeaza redarea depinde de tipul datelor ce sunt prezentate.
Figura 8.10. Modelul Player în JMF
Un Player nu permite nici un fel de control al procesarii pe care o executa si nici asupra modului în care se face redarea.
Player-ul suporta controale utilizator standard si ignora câteva restrictii operationale impuse de Clock si Controller
Figura 8.11. Player-ele JMF
8.3.2.1.1. Starile unui Player
Un Player poate fi în una din sase stari. Interfata Clock defineste cele doua stari primare: Stopped (oprit) si Started (pornit). Pentru a facilita managementul resurselor, interfata Controller divizeaza starea Stopped în alte 5 stari: Unrealized (Nerealizat), Realizing (Întelegerea), Realized (Înteles), Prefetching (Pregatirea) si Prefetched (Pregatit).
|
Figura 8.12. Starile unui Player |
Într-un mod de operare normal, un Player trece prin toate starile pana când ajunge în starea Started:
Un Player în starea Unrealized a fost initializat, dar înca nu stie nimic despre datele pe care urmeaza sa le prelucreze. Când un Player este creat pentru prima data, este în starea Unrealized;
Când procedura Realize este apelata, un Player trece din starea Unrealized în starea Realizing. Un Player în starea Realizing este în procesul de determinare a cerintelor de resurse. Aceasta determinare este efectuata o singura data. Resursele ar putea fi resursele de redare, altele decât resursele folosite exclusiv (exclusive-use resources);
Când un Player trece de starea Realizing, ajunge în starea Realized. Un Player Realized stie de ce resurse are nevoie si are informatii despre tipul datelor ce urmeaza a fi prezentate. Din cauza ca un Player Realized stie cum sa redea aceste date, el poate pune la dispozitie utilizatorului componente vizuale si controale. Conexiunea lui cu alte obiecte din sistem este existenta, dar nu îsi însuseste alte resurse care ar putea împiedica alt Player sa porneasca;
Când procedura Prefetch este apelata, un Player trece de la starea Realized la starea Prefetching. În aceasta stare Player-ul se pregateste sa prezinte datele media. La început, Player-ul încarca datele ce trebuie prezentate, obtine acces exclusiv la resursele necesare, dupa care face tot ceea ce este necesar pentru a se pregati de rulare. Procedura de Prefetch se apeleaza si în cazul în care are loc o repozitionare (spre exemplu o derulare înapoi/înainte) în prezentare sau daca o schimbare în rata de transfer necesita folosirea unor buffere suplimentare sau o procesare alternativa;
Când un Player termina toate operatiile din starea de Prefetching, trece în faza urmatoare, si anume Prefetched. În aceasta stare, Player-ul este gata de a fi pornit;
Apelarea procedurii Start pune un Player în starea Started. În aceast moment, se face o mapare a timpului de start si Clock-ul asociat este pornit, desi Player-ul s-ar putea sa astepte un anumit timp înainte de a începe prezentarea.
Un Player genereaza evenimente de tipul TransitionEvents dupa cum trece dintr-o stare în alta. Interfata CotrollerListener permite programului sa determine în care din cele sase stari se afla. Spre exemplu, când un program apeleaza o metoda asincrona unui Player sau Processor, trebuie sa asculte evenimentul potrivit pentru a determina când operatia este terminata.
Folosind acest mecanism de raportare a evenimentelor, se poate administra latenta la start a unui Player prin controlarea momentului când încep Realizing si Prefetching. De asemenea se poate determina daca Player-ul este într-o anumita stare înainte de apelarea metodelor asupra unui Player.
8.3.2.1.2. Metode disponibile în fiecare din starile Player -ului
Pentru a preveni conflictele, nu toate metodele pot fi apelate asupra unui Player în toate starile. Urmatorul tabel identifica restrictiile impuse de JMF. Daca se apeleaza o metoda care este ilegala în starea curenta a Player-ului, acesta "arunca" (throws) o eroare sau o exceptie
Metoda aplicata |
Unrealized Player |
Realized Player |
Prefetched Player |
Started Player |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*CSE - ClockStartedError
Tabel 8.4. Restrictiile metodelor aplicate asupra Player-elor
8.3.2.2. Processors (Procesoarele)
Processoarele pot fi utilizate si pentru a prezenta datele media. Un Processor este de fapt un tip de Player specializat care permite controlul asupra proceselor ce au loc asupra stream-ului de date. Un Processor suporta toate controalele de prezentare suportate de un Player. Modelul Processor este prezentat în Figura 8.13.
Figura 8.13. Modelul Processor în JMF
În afara de trimiterea datelor spre dispozitivele de redare, un Processor poate trimite datele spre o DataSource pentru a putea fi prezentate de alt Player sau Processor sau salvate într-un fisier
8.3.2.3. Controlul prezentarii
În afara controalelor standard definite de Controller, un Player sau Processor permite si ajustarea volumului.
Tipuri aditionale de interfete Control utilizator pot fi adaugate printr-o implementare particulara a unui Player sau Processor care sa modifice comportamentul controalelor si sa "expuna" componentele interfetei utilizator. Aceste controale pot fi accesate prin metoda getControls.
Spre exemplu, interfata CachingControl extinde interfata Control pentru a realiza un mecanism de afisare a unei bare de progres a unui download (download progress bar). Daca un Player poate raporta progresul lui de download, el implementeaza aceasta interfata. Pentru a afla daca un Player suporta CachingControl, trebuie apelata metoda getControl(CachingControl) sau trebuie folosita getControls pentru a obtine o lista a controalelor suportate.
Un Player sau un Processor ofera în general doua componente pentru interfata utilizator, una vizuala si una pentru panoul de control. Acestea pot fi accesate direct prin metodele getVisualComponent pentru componenta vizuala si getControlPanelComponent pentru panoul de control.
De asemenea, este posibila implementarea unor interfete utilizator. În acest caz trebuie folosit un mecanism de ascultare a evenimentelor pentru a determina când trebuie modificate componentele acestor interfete.
8.3.2.4. Evenimente de tip Controller
Evenimentul ControllerEvent generat de un Controller cum ar fi un Player sau un Processor face parte din una din urmatoarele trei categorii:
Notificarile modificarilor cum sunt RateChangeEvent, DurationUpdateEvent si FormatChangeEvent indica faptul ca unele atribute ale Controller-ului s-au modificat, de obicei în urma apelarii unei metode. Spre exemplu, un Player genereaza un eveniment RateChangeEvent când rata sa se modifica prin apelarea setRate.
Evenimentele de tranzitie (TransitionEvents) permit programului sa raspunda modificarilor starii unui Controller. Un Player genereaza evenimente de tranzitie ori de câte ori trece de la o stare la alta.
Evenimentele de încheiere, cum este ControllerClosedEvents sunt generate de un Controller când acesta se opreste. Când un Controller genereaza un eveniment ControllerClosedEvent, el nu mai poate fi folosit. Un eveniment ControllerErrorEvent este un caz special de ControllerClosedEvent. Este posibila ascultarea unui astfel de eveniment pentru a raspunde defectiunilor unui Controller si a minimiza impactul acestora asupra utilizatorului.
Figura 8.14. Evenimentele în JMF
8.3.3. Procesarea
Un Processor este un Player care primeste o DataSource la intrare, executa procese definite de utilizator asupra datelor media, dupa care trimite mai departe datele media procesate. Figura 8.15 prezinta procesarea în JMF.
Figura 8.15. Procesarea în JMF
Un Processor poate trimite datele de iesire spre un dispozitiv de prezentare sau spre o DataSource. În cel de al doilea caz, DataSource poate fi folosita ca intrare pentru un alt Player sau Processor, sau ca intrare într-un DataSink.
În timp ce procesarea executata de un Player este predefinita de echipament, un Processor permite programatorului sa defineasca tipul de procesare pe care îl vrea aplicat datelor. Aceasta procesare poate fi aplicarea de efecte, mixarea si compunerea de piste în timp real.
Figura 8.16. Stagiile prin care trece un Processor
Procesarea datelor are loc în câteva etape:
Demultiplexarea este procesul de analiza a stream-ului de intrare. Daca stream-ul contine mai multe piste, ele sunt extrase si trimise mai departe separat. Spre exemplu, un film QuickTime trebuie demultiplexat în piste audio si video separate. Demultiplexarea se realizeaza automat ori de câte ori stream-ul de intrare contine mai multe piste.
Preprocesarea este procesul de aplicare a algoritmilor de efect pistelor extrase din stream-ul de intrare.
Codarea/decodarea este procesul de conversie al fiecarei piste de date dintr-un format de intrare în altul. Când un stream de date este convertit dintr-un tip de date comprimate într-un tip de date necomprimate înseamna ca se realizeaza o operatie de decodare. Invers, conversia dintr-un tip de date necomprimate într-un tip de date comprimate se numeste operatie de codare.
Postprocesarea este procesul de aplicare a algoritmilor de efect asupra pistelor decodate.
Multiplexarea este procesul de întretesere a pistelor de date într-un singur flux de iesire. Spre exemplu, piste separate video si audio pot fi multiplexate într-un singur stream MPEG-1. Cu ajutorul Processor-ului se poate specifica tipul stream-ului de iesire. Pentru aceasta se foloseste metoda setOutputContentDescriptor.
Redarea este procesul de prezentare a datelor utilizatorului.
Procesarea fiecarei etape este realizata de o componenta de procesare separata. Aceste componente de procesare sunt plug-in-urile JMF. Daca Processor-ul suporta TrackControl, este posibila selectarea unui plug-in pentru procesarea unei piste anume. Exista cinci tipuri de plug-in-uri JMF:
Demultiplexor - parcurge stream-uri media ca WAV, MPEG sau QuickTime. Daca streamul este multiplexat, sunt extrase piste separate.
Effect - executa procesari speciale de efect asupra datelor.
Multiplexor - combina mai multe piste în una singura.
Renderer - proceseaza datele într-o pista si le trimite spre destinatie, în general spre ecran sau boxe.
8.3.3.1. Starile aditionale ale unui Processor
Un Processor are doua stari aditionale fata de un Player, si anume Configuring si Configured, stari prin care Processor-ul trece înainte de a intra în starea Realizing. În Figura 8.17 sunt prezentate toate starile prin care trece un Processor
|
Figura 8.17. Starile unui Processor |
8.3.3.2. Metode disponibile în fiecare stare a Processorului
Din moment ce un Processor este un tip de Player, restrictiile care se aplica la apelarea unui Player se aplica si la apelarea unui Processor. Unele metode specifice doar Processoar-elor sunt restrictionate doar la anumite stari. Daca se apeleaza o metoda care este ilegala în starea curenta, Processor-ul raspunde cu o eroare sau cu o exceptie
Starea Realized |
legal |
Legal |
legal |
legal |
legal |
legal |
legal |
legal |
legal |
legal |
FormatChangeException |
legal |
ClockStopped-xception |
Legal |
legal |
FormatChangeException |
legal |
Legal |
legal |
legal |
NotPrefetchedError |
Tabel 8.5. Restrictiile metodelor pentru Processor |
Starea Configured |
NotRealizedError |
legal |
NotRealizedError |
legal |
NotRealizedError |
NotRealizedError |
legal |
NotRealizedError |
legal |
NotRealizedError |
legal |
NotRealizedError |
ClockStoppedException |
Legal |
NotRealizedError |
legal |
NotRealizedError |
NotRealizedError |
NotRealizedError |
NotRealizedError |
NotPrefetchedError |
|
Starea Configuring |
NotRealizedError |
legal |
NotRealizedError |
legal |
NotRealizedError |
NotRealizedError |
NotConfiguredError |
NotRealizedError |
legal |
NotRealizedError |
NotRealizedError |
NotRealizedError |
ClockStoppedException |
Legal |
NotRealizedError |
NotConfiguredError |
NotRealizedError |
NotRealizedError |
NotRealizedError |
NotRealizedError |
NotPrefetchedError |
|
Starea Unrealized |
NotRealizedError |
legal |
NotRealizedError |
legal |
NotRealizedError |
NotRealizedError |
NotConfiguredError |
NotRealizedError |
legal |
NotRealizedError |
NotRealizedError |
NotRealizedError |
ClockStoppedException |
Legal |
NotRealizedError |
NotConfiguredError |
NotRealizedError |
NotRealizedError |
NotRealizedError |
NotRealizedError |
NotPrefetchedError |
|
Metoda aplicata |
addController |
Deallocate |
getControlPanelComponent |
getControls |
getDataOutput |
getGainControl |
getOutputContentDescriptor |
getStartLatency |
getSupportedContent-Descr |
getTimeBase |
getTrackControls |
getVisualComponent |
mapToTimeBase |
Realize |
removeController |
setOutputContentDescriptor |
setMediaTime |
setRate |
setStopTime |
setTimeBase |
syncStart |
8.3.3.3. Controlul procesarii
Exista posibilitatea de a controla operatiile pe care un Processor le executa pentru o pista, si anume folosind TrackControl pentru acea pista. Pentru a controla operatiile efectuate de Processor asupra tuturor pistelor din stream-ul de date, trebuie apelata metoda getTrackControls.
Folosind TrackControl, se poate selecta explicit tipul de plug-in care se doreste a fi folosit pentru acea pista. Pentru a afla care sunt optiunile disponibile, se poate chestiona PlugInManager-ul pentru a afla ce plug-in-uri sunt instalate.
Pentru a controla operatiile de codare/decodare executate asupra unei piste de catre un anumit Codec, trebuie apelata metoda TrackControl getControls. Aceasta metoda returneaza controalele codec-urilor disponibile pentru pista resprectiva, cum ar fi BitRateControl si QualityControl.
Daca se stie ce format a datelor de iesire se doreste, se poate folosi metoda setFormat pentru a specifica formatul si a lasa Processor-ul sa aleaga codec-ul potrivit. Alfel, se poate specifica formatul de iesire dorit când un Processor este creat folosind ProcessorModel. Un ProcessorModel defineste necesitatile de intrare si iesire pentru un Processor. Când un ProcessorModel este transmis metodei Manager create potrivite, Manager-ul face tot posibilul ca sa creeze un Processor care sa îndeplineasca conditiile cerute.
8.3.3.4. Trimiterea datelor spre destinatie
Metoda getDataOutput returneaza obiectul de la iesirea unui Processor ca o DataSource. Aceasta DataSource poate fi folosita ca intrare pentru un alt Player sau Processor sau ca intrare la o DataSink.
În Java Media Framework exista mai multe tipuri de obiecte DataSource, cum ar fi: PushDataSource, PushBufferDataSource, PullDataSource si PullBufferDataSource.
Nu toate Processoarele trimit date spre destinatie. Un Processor poate trimite datele înapoi în loc de a le trimite spre o DataSource.
8.3.4. Captura
Un dispozitiv de captura multimedia poate actiona ca o sursa de distributie de date multimedia. Spre exemplu, un microfon poate captura semnal audio brut sau o placa de captura video poate captura semnal video digital de la o camera video. Aceste dispozitive de captura poarta numele de DataSources. Exista mai multe tipuri de DataSource care pot fi folosire pentru realizarea capturii: PushDataSource, PushBufferDataSource, PullDataSource si PullBufferDataSource.
Unele dispozitive captureaza stream-uri de date multiple. Spre exemplu, o placa pentru audio/video conferinta captureaza un stream audio si unul video. DataSource-ul corespondent poate contine multiple SourceStream-uri care se mapeaza peste stream-urile de date provenite de la dispozitiv
8.3.5. Stocarea datelor si transmisia
Un DataSink este folosit pentru a citi datele de la o DataSource si de a le trimite spre o anumita destinatie (în general spre o alta destinatie decât dispozitivul de prezentare). Un anumit DataSink poate scrie date într-un fisier, poate scrie date prin retea sau poate functiona ca si un Broadcaster RTP
Ca si Player-ele, obiectele de tip DataSink sunt construite de Manager folosind DataSource. Un DataSink poate folosi un StreamWriterControl pentru a permite controlul asupra modului în care datele sunt scrise într-un fisier
Un DataSink genereaza un eveniment DataSinkEvent pentru a raporta starea sa. Un eveniment DataSinkEvent poate fi generat cu un cod care explica motivul sau poate fi generat ca unul dintre urmatoarele subtipuri:
DataSinkErrorEvent, care indica faptul ca o eroare a întrerupt procedura de scriere a datelor
EndOfStreamEvent, care indica faptul ca întregul stream a fost scris
Pentru a raspunde evenimentelor generate de un DataSink, trebuie implementata interfata DataSinkListener.
8.3.6. Extensibilitatea
Este posibila extinderea JMF prin implementarea unor plug-in-uri, dispozitive de tratare a datelor si surse de date utilizator
Prin implementarea interfetelor unui plug-in JMF sunt posibile accesul direct si manipularea directa la datele asociate unui Processor
Implementarea interfetei Demultiplexer permite controlul procesului de extragere al pistelor individuale din streamul de date multiplexat;
Implementarea interfetei Codec permite efectuarea operatiilor de procesare necesare decodarii datelor comprimate, de conversie dintr-un anumit format în altul, de codare a datelor brute într-un format comprimat;
Implementarea interfetei Effect permite efectuarea unor operatii utilizator asupra datelor;
Implementarea interfetei Multiplexer permite specificarea modului în care pistele individuale sunt combinate pentru a forma un singur stream de iesire pentru un Processor
Implementarea interfetei Render permite controlul asupra modului în care datele sunt procesate si trimise spre dispozitivele de iesire.
NOTĂ: API-ul JMF pentru plug-in uri este parte componenta a API-ului JMF, dar Player-ele si Processoarele nu trebuie neaparat sa suporte plug-in-uri. Aceste plug-in-uri nu functioneaza cu Player-ele si Processoarele JMF 1.0. Versiunea 2.0 a JMF dezvoltata de SUN Microsystems, Inc. si IBM Corporation suporta integral acest API .
|