Napredak na JMF i Java Media API-ima

Moj prvi članak o JavaWorldu bio je u Java Media Framework-u (JMF). Kako su razni API-ji za medije sazrijevali, osjećam da su se stvari zaokružile. Stoga ću svoj konačni stupac Programiranje medija posvetiti ponovnom posjetu JMF-u i općenitom stanju svih Java Media API-ja.

Dogodile su se neke značajne promjene u JMF-u i drugim Java Media tehnologijama, tvrtkama koje razvijaju njihove implementacije i njihovoj dostupnosti za programere. Ovaj članak prema potrebi ažurira materijal iz prethodnih članaka.

Važan podsjetnik: Java Media Framework je specifični API za sinkronizaciju multimedijskih tokova (datoteka, mrežnih tokova i tako dalje). To je jedan od nekoliko Java Media API-ja, koji također uključuju Java 2D, Java 3D, Java Speech i tako dalje. Javni okvir za medije nazivam JMF, koji rezervira termin Java Media za cijelu kolekciju multimedijskih API-ja.

Povijest i osnove JMF-a

Od JMF 1.0, zvanog Java Media Player API, napisao sam sljedeće u travnju 1997. (vidi Resurse):

API Java Media Player, dio Java Media Framework-a (JMF), omogućuje Java programerima da lako ugrađuju audio i video u aplete i programe. Statička i streaming multimedija podržani su s bilo kojeg važećeg URL-a. JMF uređajima mogu upravljati drugi uređaji, pružajući sinkronu reprodukciju višestrukih audio i video uzoraka.

Ove informacije i dalje vrijede za ažuriranja i dopune u posljednje dvije godine. Međutim, JMF je razvio nove mogućnosti i povećao opseg, posebno s nadolazećim izdanjem 2.0 API-ja (očekuje se u drugoj polovici 1999.).

Igrači JMF industrije

Prvo, pogledajmo igrače u industriji. Sun, Silicon Graphics (SGI) i Intel sredinom 1998. dizajnirali su i specificirali originalni JMF 1.0. U međuvremenu od početne verzije API-ja, i SGI i Intel povukli su se iz postupka specifikacije JMF-a. Neko je vrijeme u korisničkoj zajednici JMF postojala značajna zabrinutost da je Sun jedini dobavljač koji podržava JMF. Ova je situacija bila nepoželjna.

Srećom, krajem 1998. IBM je uskočio sa zanimanjem za JMF. Ubrzo nakon što se IBM pridružio Sunu, objavljena je potpuno Java implementacija 1.0 API-ja (prosinac 1998). Ova implementacija, poznata kao JMF 1.1 za Java platforme, podržava ograničenu, ali značajnu podskupinu vrsta sadržaja i protokola podržanih implementacijama Win32 i Solaris-ov JMF 1.1 (poznatim kao paketi performansi)). Dostupnost cjelovitog Java JMF 1.1 bila je glavna prekretnica za JMF, jer je tehnologija postala dostupna za bilo koje Java 1.1 usklađeno ili Java 2 runtime. U stvari, implementacija JMF 1.1 Java čak je dostupna i u web orijentiranoj verziji s alatima koji omogućavaju programerima da uključe samo relevantne JMF klase u JAR datoteku za preuzimanje sa svojim JMF apletima. To omogućuje postavljanje apleta temeljenih na JMF-u na web poslužitelju za upotrebu u bilo kojem pregledniku koji podržava Java 1.1. I Netscape i Microsoft podržavaju Javu 1.1 - i samim tim JMF 1.1 za Javu - u nedavnim izdanjima Navigatora i Internet Explorera u pregledniku.

IBM pomaže Sunu da definira kodirani JMF 2.0 API, koji će sadržavati specifikaciju i pružiti referentnu implementaciju sljedećeg JMF API-ja: Java Media Capture. Nadajmo se da će IBM smisliti kako naknadno uvesti JMF funkcionalnost u neke od svojih softverskih proizvoda orijentiranih na Javu - potencijalno dobru stvar za dugovječnost JMF tehnologije.

Što je novo u JMF 2.0 u odnosu na 1.0?

API JMF 1.0 navodi komponente potrebne za reprodukciju sinkroniziranog zvuka i videa. Pogledajte moj prethodni članak o JMF-u (pogledajte Resurse) za pregled mogućnosti JMF-a 1.0.

JMF 2.0 donosi nekoliko ključnih dodataka specifikacijama:

  • Snimanje zvuka i videa
  • Streaming audio i video zapisa, a time i mogućnost izrade all-Java streaming poslužitelja uz klijente
  • Podržana podrška za kodek unutar playera

Za više informacija o JMF 2.0 i njegovim novim mogućnostima, pogledajte Vodič za Java Media Framework Programmer (vidi Resurse), trenutno dostupan u verziji 0.5 za rani pristup.

Instalacija razvojnih alata JMF i vrijeme izvođenja

I Silicon Graphics i Intel uklonili su prethodne verzije JMF-a sa svojih web stranica. Međutim, najnovije referentne implementacije (označene kao JMF 1.1, u skladu s 1.0 API specifikacijama) za platforme Win32, Solaris i Java možete preuzeti s web mjesta Sun (pogledajte Resursi).

Imajte na umu da se u dokumentaciji za potpuno Java-verziju posebno spominje AIX, što ukazuje da je IBM testirao ovaj softver na svom AIX Java runtime-u. Očekujem da će buduća izdanja JMF-a (2.0 i novije) posebno podržati IBM operativna okruženja, bilo putem čisto Java implementacije ili izvornih implementacija specifičnih za OS.

Ažurirani primjeri JMF-a

Ažurirao sam primjer JMF 1.0 beta kompatibilnog iz mog prethodnog JMF članka da bi se izvodio u okruženjima kompatibilnim s API-jem JMF 1.0. Možete preuzeti primjer koda i isprobati ga pod implementacijama JMF 1.1 koristeći vlastite medijske datoteke. Aplet bi se također trebao izvoditi na runtimesima JMF 2.0 kada postanu dostupni. (Da biste preuzeli sve datoteke povezane s ovim člankom u zip formatu, pogledajte Resursi.)

001 // Komentirajte sljedeću izjavu paketa za zasebnu kompilaciju. 002 // paket com.javaworld.media.jmf; 003 004 import java.applet. *; 005 import java.awt. *; 006 import java.net. *; 007 import java.io. *; 008 import javax.media. *; 009 010 / ** 011 * JMF11Applet ažurira JMFApplet iz članka iz travnja 1997. 012 * JavaWorld radi usklađenosti s API-jem JMF 1.1. Molimo 013 * pogledajte članak na:

014 * //www.javaworld.com/jw-04-1997/jw-04-jmf.html 015 *

016 * Uz to, JMF11Applet je prerađen da bi 017 * koristio model događaja Java 1.1 (i noviji). Ova verzija 018 * razvijena je i testirana na Javi 2 019 * i JMF 1.1 potpuno Java implementaciji, svibanj 1999. 020 *

021 * Ovaj se aplet može rasporediti na javne web poslužitelje 022 * pomoću jmf-server.jar navedenog u preuzimanju JMF 1.1 023 * za web poslužitelje. Ova JAR arhiva sadrži 024 * potrebne JMF all-Java runtime klase. JMF11Applet 025 * raspoređen je na ovaj način za stupac 026, lipanj 1999:

027 * //www.javaworld.com/jw-06-1999/jw-06-media.html 028 * 029 * @author Bill Day 030 * @version 1.1 031 * @see javax.media.ControllerEvent 032 * @see javax .media.ControllerListener 033 * @see javax.media.Manager 034 * @see javax.media.NoPlayerException 035 * @see javax.media.Player 036 * @see javax.media.RealizeCompleteEvent 037 ** / 038 039 JMF11Applet javne klase se proteže Aplet implementira ControllerListener {040 privatni URL myURL = null; 041 privatni igrač myPlayer = null; 042 private Component myVisual = null; 043 privatna komponenta myControls = null; 044 privatna ploča visualPanel = null; 045 046 / ** 047 * Inicijalizirajte JMF11Applet. Izložimo sučelje i 048 * kreiramo naš player u init (). 049 ** / 050 javna void init () {051 super.init (); 052 053 // Navedite AWT Layout Manager. 054 setLayout (novi BorderLayout ());055 056 // Učitavanje URL-a s web stranice JMF11Applet je ugrađen u. 057 String resource = getParameter ("ASSET"); 058 059 // Provjerite URL i stvorite URL objekt koji će ga zadržati. 060 if (asset.equals ("")) {061 // nismo unijeli sredstvo u aplet. 062} else {063 probaj {064 myURL = novi URL (getDocumentBase (), sredstvo); 065} catch (MalformedURLException e) {066 // Uneli smo nepotpuni materijal ili izgradili netočan URL. 067 // Robusniji aplet trebao bi to riješiti graciozno. 068} 069} 070 pokušaj {071 // Evo zanimljivog dijela. Upravitelj se koristi za 072 // stvaranje stvarnog playera za ovaj URL. Zatim 073 // dodajemo JMF11Applet kao ControllerListener za myPlayer. 074 // To nam omogućuje da reagiramo na RealizeCompleteEvents. 075 myPlayer = Manager.createPlayer (myURL); 076 myPlayer.addControllerListener (ovo);077} catch (IOException e) {078 // Naišao je na problem s I / O; Izlaz. 079 System.out.println ("I / O problem pri pokušaju stvaranja playera ... izlazak"); 080 System.exit (1); 081} catch (NoPlayerException e) {082 // Nije moguće vratiti korisnog igrača; Izlaz. 083 System.out.println ("Nema vraćenog korisnog igrača ... izlazak"); 084 System.exit (1); 085} 086} 087 088 / ** 089 * Zamijenite zadani način pokretanja apleta da biste pozvali 090 * * Player () playera. To će prvo izvršiti realizaciju, koja zauzvrat 091 * pokreće završne bitove izgradnje GUI-a u metodi controUpdate () 092 *. Ne pokrećemo automatski reprodukciju: korisniku treba 093 * da klikne na gumb "reproduciraj" u našem apletu da bi započeo reprodukciju uzorka medija 094 *. 095 ** / 096 javni void start () {097 myPlayer.realize ();098} 099 100 101 / ** 102 * Zamijenite zadanu metodu zaustavljanja apleta da biste pozvali myPlayer.stop () 103 * i myPlayer.deallocate () kako bismo pravilno oslobodili resurse 104 * ako netko izađe s ove stranice u svom pregledniku. 105 ** / 106 javna void stop () {107 myPlayer.stop (); 108 myPlayer.deallocate (); 109} 110 111 / ** 112 * Budući da moramo znati kada realizacija završi, koristimo 113 * controllerUpdate () za obradu RealizeCompleteEvents. 114 * Kad primimo RealizeCompleteEvent, rasporedimo 115 * i prikazujemo video komponentu i kontrole u našem grafičkom sučelju apleta 116 *. 117 ** / 118 javna void controllerUpdate (ControllerEvent event) {119 if (instance of RealizeCompleteEvent) {120 //System.out.println("Received RCE ... "); 121 // Sad kad imamo Realiziranog igrača,možemo dobiti 122 // VisualComponent i ControlPanelComponent i spakirati 123 // u naš aplet. 124 myVisual = myPlayer.getVisualComponent (); 125 if (myVisual! = Null) {126 // Da bih osigurao da BorderLayout ne mijenja veličinu VisualComponenta 127 //, ugnijezdiću ga 128 // unutar visualPanela pomoću FlowLayout. 129 visualPanel = nova ploča (); 130 visualPanel.setLayout (novi FlowLayout ()); 131 visualPanel.add (myVisual); 132 dodaj (visualPanel, BorderLayout.CENTER); 133 //System.out.println("Added VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 if (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("Dodane kontrole ... "); 139} 140 // invalidate (); 141 potvrditi (); 142} 143 // Inače jednostavno konzumiramo događaj. 144} 145}124 myVisual = myPlayer.getVisualComponent (); 125 if (myVisual! = Null) {126 // Da bih osigurao da BorderLayout ne mijenja veličinu VisualComponenta 127 //, ugnijezdiću ga 128 // unutar visualPanela pomoću FlowLayout. 129 visualPanel = nova ploča (); 130 visualPanel.setLayout (novi FlowLayout ()); 131 visualPanel.add (myVisual); 132 dodaj (visualPanel, BorderLayout.CENTER); 133 //System.out.println("Added VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 if (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("Dodane kontrole ... "); 139} 140 // invalidate (); 141 potvrditi (); 142} 143 // Inače jednostavno konzumiramo događaj. 144} 145}124 myVisual = myPlayer.getVisualComponent (); 125 if (myVisual! = Null) {126 // Da bih osigurao da BorderLayout ne mijenja veličinu VisualComponenta 127 //, ugnijezdiću ga 128 // unutar visualPanela pomoću FlowLayout. 129 visualPanel = nova ploča (); 130 visualPanel.setLayout (novi FlowLayout ()); 131 visualPanel.add (myVisual); 132 dodaj (visualPanel, BorderLayout.CENTER); 133 //System.out.println("Added VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 if (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("Dodane kontrole ... "); 139} 140 // invalidate (); 141 potvrditi (); 142} 143 // Inače jednostavno konzumiramo događaj. 144} 145}= null) {126 // Kako bih osigurao da BorderLayout ne mijenja veličinu VisualComponenta 127 //, ugnijezdiću ga 128 // unutar visualPanela pomoću FlowLayout. 129 visualPanel = nova ploča (); 130 visualPanel.setLayout (novi FlowLayout ()); 131 visualPanel.add (myVisual); 132 dodaj (visualPanel, BorderLayout.CENTER); 133 //System.out.println("Added VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 if (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("Dodane kontrole ... "); 139} 140 // invalidate (); 141 potvrditi (); 142} 143 // Inače jednostavno konzumiramo događaj. 144} 145}= null) {126 // Kako bih osigurao da BorderLayout ne mijenja veličinu VisualComponenta 127 //, ugnijezdiću ga 128 // unutar visualPanela pomoću FlowLayout. 129 visualPanel = nova ploča (); 130 visualPanel.setLayout (novi FlowLayout ()); 131 visualPanel.add (myVisual); 132 dodaj (visualPanel, BorderLayout.CENTER); 133 //System.out.println("Added VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 if (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("Dodane kontrole ... "); 139} 140 // invalidate (); 141 potvrditi (); 142} 143 // Inače jednostavno konzumiramo događaj. 144} 145}133 //System.out.println("Added VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 if (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("Dodane kontrole ... "); 139} 140 // invalidate (); 141 potvrditi (); 142} 143 // Inače jednostavno konzumiramo događaj. 144} 145}133 //System.out.println("Added VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 if (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("Dodane kontrole ... "); 139} 140 // invalidate (); 141 potvrditi (); 142} 143 // Inače jednostavno konzumiramo događaj. 144} 145}

Uključio sam jednostavan primjer HTML dokumenta, example.html (koji možete odmah isprobati u svom pregledniku klikom ovdje), kako bi vam pokazao kako ugraditi aplet u svoje web stranice. Jednostavno promijenite medijsku datoteku u ASSEToznaci i krenite!

U ovom primjeru koristio sam JMF 1.1 za preuzimanje web poslužitelja (dokumentirano na web mjestu JMF) kako bih omogućio JMF11Appletautomatsko preuzimanje jmf-server.jar, arhivu koda koja sadrži potrebne klase izvršavanja JMF-a. To omogućuje izvršavanje apleta u bilo kojem pregledniku kompatibilnom s Java 1.1, bez softvera koji bi krajnji korisnik mogao instalirati. (Imajte na umu da verzija JMF za web poslužitelje također uključuje alat za prilagodbu JMFCustomizer, koji će vam potencijalno omogućiti uklanjanje još više nepotrebnih klasa iz JMF JAR datoteke. Međutim, ovaj alat trenutno ne radi pod Javom 2, jer koristi zastarjeli softver naziv paketa za Swing.)

U određenom primjeru ugrađenom u example.html učitavamo WAV datoteku (welcome.wav), utvrđujemo odgovarajuće kontrolne komponente koje ćemo učiniti dostupnima (bez video komponente, jer je ovo medijska datoteka samo sa zvukom) i reproduciramo multimediju datoteka. Imajte na umu da će WAV datoteci (600 KB) i JMF klasama (570 KB) biti potrebno nekoliko minuta za preuzimanje na vaš uređaj, ovisno o brzini veze.

Nakon raščlanjivanja primjera stranice, preglednici kompatibilni s Java 1.1 trebali bi automatski učitati aplet i podržavati JMF klase s web-poslužitelja JavaWorld . Nakon što se aplet učita i pokrene, možete pritisnuti gumb Reproduciraj da biste započeli reprodukciju WAV zvučne datoteke. Pokušajte repozicionirati reprodukciju pomoću trake za pomicanje i zaustaviti i ponovo pokrenuti reprodukciju pomoću gumba Pause / Play.

Implementacija JMF 1.1 Java platforme koristi widgete potpuno Java za svoje kontrole, tako da kontrole imaju isti izgled od preglednika do preglednika i od platforme do platforme. Primijetite kako izgleda da aplet radi u JVM-u Netscape Communicatora na Solarisu 7 i Microsoftovom JVM-u u Internet Exploreru na Win32.

Gumb s oznakom i pruža informacije o reprodukciji medijske datoteke u JMF apletu. Kliknite ovu vezu s informacijama da biste dobili detalje o WAV datoteci koja se izvodi na ovoj web stranici.