Kemajuan di API Media JMF dan Java

Artikel JavaWorld pertama saya ketika saya berada di Java Media Framework (JMF). Oleh kerana pelbagai API Media telah matang, saya merasakan bahawa semuanya telah berputar sepenuhnya. Oleh itu, saya akan mendedikasikan lajur Pengaturcaraan Media terakhir saya untuk meninjau semula JMF dan keadaan umum semua Java Media API.

Terdapat beberapa perubahan penting dalam JMF dan teknologi Java Media lain, perusahaan yang mengembangkan implementasinya, dan ketersediaannya untuk pengembang. Artikel ini mengemas kini bahan dari artikel sebelumnya sesuai.

Peringatan penting: Java Media Framework adalah API khusus untuk menyegerakkan aliran multimedia (fail, aliran rangkaian, dan sebagainya). Ini adalah salah satu dari beberapa Java Media API, yang juga termasuk Java 2D, Java 3D, Java Speech, dan sebagainya. Saya merujuk Java Media Framework sebagai JMF, menggunakan istilah Java Media untuk keseluruhan koleksi API multimedia.

Sejarah dan asas JMF

Dari JMF 1.0, alias Java Media Player API, saya menulis yang berikut pada bulan April 1997 (lihat Sumber):

Java Media Player API, bagian dari Java Media Framework (JMF), memungkinkan pengaturcara Java menyematkan audio dan video dengan mudah dalam applet dan aplikasi. Kedua-dua multimedia statis dan streaming disokong dari sebarang URL yang sah. Pemain JMF mungkin dikendalikan oleh pemain lain, menyediakan pemutaran segerak pelbagai sampel audio dan video.

Maklumat ini masih berlaku dengan kemas kini dan penambahan dua tahun terakhir. JMF, bagaimanapun, telah mengembangkan kemampuan baru dan berkembang dalam ruang lingkup, terutama dengan pelepasan 2.0 API yang akan datang (dijangka pada separuh kedua tahun 1999).

Pemain industri JMF

Pertama, mari kita lihat pemain industri. Sun, Silicon Graphics (SGI), dan Intel merancang dan menentukan JMF 1.0 yang asli pada pertengahan tahun 1998. Untuk sementara sejak versi awal API, kedua SGI dan Intel telah menarik diri dari proses spesifikasi JMF. Untuk sementara waktu, terdapat kebimbangan yang ketara dalam komuniti pengguna JMF bahawa Sun adalah satu-satunya vendor yang menyokong JMF. Keadaan ini tidak diingini.

Nasib baik, pada akhir tahun 1998 IBM melangkah dengan minat dalam JMF. Tidak lama setelah IBM bergabung dengan Sun, implementasi semua API dari Java 1.0 diluncurkan (Disember 1998). Pelaksanaan ini, yang dikenali sebagai JMF 1.1 untuk platform Java, menyokong subkumpulan kandungan dan protokol yang terhad tetapi signifikan yang disokong oleh implementasi J32F32 asli Win32 dan Solaris (dikenali sebagai pek prestasi). Ketersediaan JMF 1.1 semua Java adalah tonggak utama bagi JMF, di mana teknologi itu tersedia untuk mana-mana Java 1.1 atau Java 2 runtime. Sebenarnya, pelaksanaan Java JMF 1.1 bahkan boleh didapati dalam versi berorientasi Web dengan alat yang membolehkan pembangun memasukkan hanya kelas JMF yang relevan dalam fail JAR untuk dimuat turun dengan applet JMF mereka. Ini membolehkan seseorang menggunakan applet berasaskan JMF pada pelayan Web untuk digunakan oleh penyemak imbas yang mematuhi Java 1.1. Netscape dan Microsoft menyokong Java 1.1 - dan oleh itu JMF 1.1 untuk Java - dalam peluncuran penyemak imbas terbaru Navigator dan Internet Explorer masing-masing.

IBM membantu Sun untuk menentukan kode JMF 2.0 API, yang akan merangkumi spesifikasi dan memberikan rujukan pelaksanaan API JMF berikutnya: Java Media Capture. Mari berharap IBM mengetahui bagaimana untuk kemudian memasukkan fungsi JMF ke dalam beberapa produk perisian berasaskan Java yang berorientasikan perniagaan - satu perkara yang berpotensi baik untuk jangka panjang teknologi JMF.

Apa yang baru dalam JMF 2.0 berbanding 1.0?

JMF 1.0 API menentukan komponen yang diperlukan untuk mengendalikan main balik audio dan video yang diselaraskan. Sila rujuk artikel JMF saya sebelumnya (lihat Sumber) untuk meninjau kemampuan JMF 1.0.

JMF 2.0 membuat beberapa penambahan utama pada spesifikasi:

  • Rakaman audio dan video
  • Penstriman audio dan video, dan dengan itu kemungkinan untuk membina pelayan streaming semua Java sebagai tambahan kepada klien
  • Sokongan codec terpasang dalam pemain

Untuk maklumat lebih lanjut mengenai JMF 2.0 dan kemampuan barunya, lihat Panduan Pemrograman Kerangka Media Java (lihat Sumber), yang saat ini tersedia dalam akses awal versi 0.5.

Pemasangan alat pengembangan dan jangka masa JMF

Kedua-dua Silicon Graphics dan Intel telah membuang versi JMF sebelumnya dari laman web masing-masing. Namun, Anda dapat memuat turun implementasi rujukan terbaru (dilambangkan JMF 1.1, sesuai dengan spesifikasi API 1.0) untuk platform Win32, Solaris, dan Java dari laman Sun (lihat Sumber).

Perhatikan bahawa dokumentasi untuk versi semua Java secara khusus menyebutkan AIX, yang menunjukkan bahawa IBM telah menguji perisian ini pada waktu berjalan AIX Java. Saya mengharapkan pelepasan JMF di masa depan (2.0 dan seterusnya) untuk secara khusus menyokong persekitaran operasi IBM, sama ada melalui pelaksanaan Java yang murni atau implementasi asli khusus OS.

Contoh JMF yang dikemas kini

Saya telah mengemas kini contoh pematuhan beta JMF 1.0 dari artikel JMF saya sebelumnya untuk dijalankan di persekitaran yang mematuhi API JMF 1.0. Anda boleh memuat turun kod contoh dan mencubanya di bawah pelaksanaan JMF 1.1 menggunakan fail media anda sendiri. Applet juga harus berjalan pada waktu berjalan JMF 2.0 apabila sudah tersedia. (Untuk memuat turun semua fail yang berkaitan dengan artikel ini dalam format zip, lihat Sumber.)

001 // Komen penyataan pakej berikut untuk disusun secara berasingan. 002 // pakej 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 mengemas kini JMFApplet dari artikel JavaWorld April 1997 012 * untuk pematuhan API JMF 1.1. Sila 013 * rujuk artikel di:

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

016 * Sebagai tambahan, JMF11Applet telah dikerjakan semula untuk 017 * menggunakan model acara Java 1.1 (dan seterusnya). Versi 018 * ini telah dikembangkan dan diuji pada Java 2 019 * dan implementasi JMF 1.1 all-Java, Mei 1999. 020 *

021 * Applet ini dapat disebarkan ke pelayan Web awam 022 * menggunakan jmf-server.jar yang disediakan dalam JMF 1.1 023 * untuk muat turun Pelayan Web. Arkib JAR ini mengandungi 024 * kelas JMF semua-Java runtime yang diperlukan. JMF11Applet 025 * telah digunakan dengan cara ini untuk lajur Jun 1999 026 *:

027 * //www.javaworld.com/jw-06-1999/jw-06-media.html 028 * 029 * @author Bill Day 030 * @versi 1.1 031 * @sihat javax.media.ControllerEvent 032 * @sihat 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 kelas awam JMF11Applet Applet melaksanakan ControllerListener {040 URL peribadi myURL = null; 041 pemain peribadi myPlayer = null; 042 komponen peribadi myVisual = null; 043 komponen peribadi myControls = null; 044 panel peribadi visualPanel = null; 045 046 / ** 047 * Permulaan JMF11Applet. Kami meletakkan antara muka dan 048 * membuat pemain kami di init (). 049 ** / 050 awam tidak sah init () {051 super.init (); 052 053 // Tentukan Pengurus Layout AWT. 054 setLayout (BorderLayout baru ());055 056 // Muatkan URL dari laman Web JMF11Applet tertanam dalam. 057 String aset = getParameter ("ASET"); 058 059 // Periksa URL dan buat objek URL untuk menahannya. 060 jika (asset.equals ("")) {061 // kami belum memasukkan aset ke dalam applet. 062} lain {063 cuba {064 myURL = URL baru (getDocumentBase (), aset); 065} tangkapan (MalformedURLException e) {066 // Kami memasukkan aset yang tidak lengkap atau membina URL yang salah. 067 // Applet yang lebih mantap harus menangani ini dengan baik. 068} 069} 070 cuba {071 // Inilah sedikit yang menarik. Pengurus digunakan untuk 072 // membuat pemain sebenar untuk URL ini. Kami kemudian 073 // menambahkan JMF11Applet sebagai ControllerListener untuk myPlayer. 074 // Ini membolehkan kita bertindak balas terhadap RealizeCompleteEvents. 075 myPlayer = Pengurus.createPlayer (myURL); 076 myPlayer.addControllerListener (ini);077} tangkapan (IOException e) {078 // Menghadapi beberapa masalah dengan I / O; jalan keluar. 079 System.out.println ("Masalah I / O cuba membuat pemain ... keluar"); 080 System.exit (1); 081} tangkapan (NoPlayerException e) {082 // Tidak dapat mengembalikan Pemain yang boleh digunakan; jalan keluar. 083 System.out.println ("Pemain tidak boleh digunakan dikembalikan ... keluar"); 084 System.exit (1); 085} 086} 087 088 / ** 089 * Ganti kaedah permulaan applet lalai untuk memanggil Pemain 090 * sedar (). Ini terlebih dahulu akan mewujudkan, yang pada gilirannya 091 * mencetuskan bit akhir bangunan GUI dalam kaedah controllerUpdate () 092 *. Kami tidak memulakan main balik secara automatik: Pengguna memerlukan 093 * untuk mengklik butang "mainkan" di applet kami untuk mula memainkan sampel media 094 *. 095 ** / 096 awam tidak sah bermula () {097 myPlayer.realize ();098} 099 100 101 / ** 102 * Ganti kaedah berhenti applet lalai untuk memanggil myPlayer.stop () 103 * dan myPlayer.deallocate () agar kami membebaskan sumber dengan betul 104 * jika seseorang keluar dari halaman ini di penyemak imbas mereka. 105 ** / 106 perhentian kosong awam () {107 myPlayer.stop (); 108 myPlayer.deallocate (); 109} 110 111 / ** 112 * Oleh kerana kita mesti tahu apabila sedar selesai, kita menggunakan 113 * controllerUpdate () untuk menangani RealizeCompleteEvents. 114 * Apabila kami menerima RealizeCompleteEvent, kami menyusun 115 * dan memaparkan komponen dan kawalan video dalam GUI applet 116 * kami. 117 ** / 118 public void controllerUpdate (ControllerEvent event) {119 if (event instanceof RealizeCompleteEvent) {120 //System.out.println("Received RCE ... "); 121 // Sekarang kita mempunyai pemain yang disedari,kita boleh mendapatkan 122 // VisualComponent dan ControlPanelComponent dan memasukkan 123 // ke dalam applet kami. 124 myVisual = myPlayer.getVisualComponent (); 125 if (myVisual! = Null) {126 // Untuk memastikan bahawa VisualComponent 127 // tidak diubah saiznya oleh BorderLayout, saya meletakkannya 128 // dalam visualPanel menggunakan FlowLayout. 129 visualPanel = Panel baru (); 130 visualPanel.setLayout (FlowLayout baru ()); 131 visualPanel.add (myVisual); 132 tambah (visualPanel, BorderLayout.CENTRE); 133 //System.out.println("Tambah VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 jika (myControls! = Null) {137 tambah (myControls, BorderLayout.SOUTH); 138 //System.out.println("Tambah kawalan ... "); 139} 140 // tidak sah (); 141 mengesahkan (); 142} 143 // Jika tidak, kita hanya menghabiskan acara itu. 144} 145}124 myVisual = myPlayer.getVisualComponent (); 125 if (myVisual! = Null) {126 // Untuk memastikan bahawa VisualComponent 127 // tidak diubah saiznya oleh BorderLayout, saya meletakkannya 128 // dalam visualPanel menggunakan FlowLayout. 129 visualPanel = Panel baru (); 130 visualPanel.setLayout (FlowLayout baru ()); 131 visualPanel.add (myVisual); 132 tambah (visualPanel, BorderLayout.CENTRE); 133 //System.out.println("Tambah VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 jika (myControls! = Null) {137 tambah (myControls, BorderLayout.SOUTH); 138 //System.out.println("Tambah kawalan ... "); 139} 140 // tidak sah (); 141 mengesahkan (); 142} 143 // Jika tidak, kita hanya menghabiskan acara itu. 144} 145}124 myVisual = myPlayer.getVisualComponent (); 125 if (myVisual! = Null) {126 // Untuk memastikan bahawa VisualComponent 127 // tidak diubah saiznya oleh BorderLayout, saya meletakkannya 128 // dalam visualPanel menggunakan FlowLayout. 129 visualPanel = Panel baru (); 130 visualPanel.setLayout (FlowLayout baru ()); 131 visualPanel.add (myVisual); 132 tambah (visualPanel, BorderLayout.CENTRE); 133 //System.out.println("Tambah VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 jika (myControls! = Null) {137 tambah (myControls, BorderLayout.SOUTH); 138 //System.out.println("Tambah kawalan ... "); 139} 140 // tidak sah (); 141 mengesahkan (); 142} 143 // Jika tidak, kita hanya menghabiskan acara itu. 144} 145}= null) {126 // Untuk memastikan bahawa VisualComponent 127 // tidak diubah ukurannya oleh BorderLayout, saya meletakkannya 128 // dalam visualPanel menggunakan FlowLayout. 129 visualPanel = Panel baru (); 130 visualPanel.setLayout (FlowLayout baru ()); 131 visualPanel.add (myVisual); 132 tambah (visualPanel, BorderLayout.CENTRE); 133 //System.out.println("Tambah VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 jika (myControls! = Null) {137 tambah (myControls, BorderLayout.SOUTH); 138 //System.out.println("Tambah kawalan ... "); 139} 140 // tidak sah (); 141 mengesahkan (); 142} 143 // Jika tidak, kita hanya menghabiskan acara itu. 144} 145}= null) {126 // Untuk memastikan bahawa VisualComponent 127 // tidak diubah saiznya oleh BorderLayout, saya meletakkannya 128 // dalam visualPanel menggunakan FlowLayout. 129 visualPanel = Panel baru (); 130 visualPanel.setLayout (FlowLayout baru ()); 131 visualPanel.add (myVisual); 132 tambah (visualPanel, BorderLayout.CENTRE); 133 //System.out.println("Tambah VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 jika (myControls! = Null) {137 tambah (myControls, BorderLayout.SOUTH); 138 //System.out.println("Tambah kawalan ... "); 139} 140 // tidak sah (); 141 mengesahkan (); 142} 143 // Jika tidak, kita hanya menghabiskan acara tersebut. 144} 145}133 //System.out.println("Tambah VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 jika (myControls! = Null) {137 tambah (myControls, BorderLayout.SOUTH); 138 //System.out.println("Tambah kawalan ... "); 139} 140 // tidak sah (); 141 mengesahkan (); 142} 143 // Jika tidak, kita hanya menghabiskan acara itu. 144} 145}133 //System.out.println("Tambah VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 jika (myControls! = Null) {137 tambah (myControls, BorderLayout.SOUTH); 138 //System.out.println("Tambah kawalan ... "); 139} 140 // tidak sah (); 141 mengesahkan (); 142} 143 // Jika tidak, kita hanya menghabiskan acara tersebut. 144} 145}

Saya telah memasukkan dokumen HTML contoh sederhana, example.html (yang boleh anda cuba di penyemak imbas anda sekarang dengan mengklik di sini), untuk menunjukkan kepada anda cara memasukkan applet ke dalam laman Web anda sendiri. Cukup ubah fail media dalam ASSETtag dan pergi!

Untuk contoh ini, saya menggunakan muat turun JMF 1.1 untuk Pelayan Web (didokumentasikan di laman web JMF) untuk membolehkan JMF11Appletmemuat turun secara automatik jmf-server.jar, arkib kod yang mengandungi kelas runtime JMF yang diperlukan. Ini membolehkan applet dijalankan di mana-mana penyemak imbas yang kompatibel dengan Java 1.1, tanpa perisian untuk dipasang oleh pengguna akhir. (Perhatikan bahawa versi JMF untuk Pelayan Web juga menyertakan alat penyesuaian JMFCustomizer, yang berpotensi memungkinkan anda menghapus kelas yang lebih tidak diperlukan dari fail JMF JAR. Alat ini saat ini tidak berfungsi di bawah Java 2, namun, karena ia menggunakan usang nama pakej untuk Swing.)

Dalam contoh tertentu yang disematkan di example.html , kami memuat fail WAV (welcome.wav), memastikan komponen kawalan yang sesuai untuk disediakan (tidak ada komponen video, kerana ini adalah fail media yang hanya suara), dan memainkan semula multimedia fail. Perhatikan bahawa fail WAV (600 KB) dan kelas JMF (570 KB) mungkin memerlukan beberapa minit untuk memuat turun ke mesin anda bergantung pada kelajuan sambungan anda.

Setelah menguraikan halaman contoh, penyemak imbas yang mematuhi Java 1.1 harus memuat applet dan menyokong kelas JMF secara automatik dari pelayan Web JavaWorld . Setelah applet dimuat dan dijalankan, anda boleh menekan butang Putar untuk memulakan main semula fail suara WAV. Cuba ubah semula main balik menggunakan bar tatal dan berhenti sebentar dan mulakan semula main balik menggunakan butang Jeda / Main.

Pelaksanaan platform JMF 1.1 Java menggunakan widget semua-Java untuk kawalannya, sehingga kontrol memiliki penampilan yang sama dari penyemak imbas ke penyemak imbas dan platform ke platform. Perhatikan bagaimana applet kelihatan berjalan di dalam Netscape Communicator's JVM pada Solaris 7 dan Microsoft JVM di Internet Explorer pada Win32.

Butang berlabel i memberikan maklumat mengenai fail media yang dimainkan di applet JMF. Klik pada pautan maklumat ini untuk mendapatkan maklumat mengenai fail WAV yang berjalan di laman Web ini.