Kemajuan di JMF dan Java Media API

Artikel JavaWorld pertama saya saat berada di Java Media Framework (JMF). Saat berbagai API Media telah matang, saya merasa hal-hal telah menjadi lingkaran penuh. Oleh karena itu, saya akan mendedikasikan kolom Pemrograman Media terakhir saya untuk meninjau kembali JMF dan keadaan umum semua Java Media API.

Ada beberapa perubahan penting dalam JMF dan teknologi Java Media lainnya, perusahaan yang mengembangkan implementasinya, dan ketersediaannya untuk pengembang. Artikel ini memperbarui materi dari artikel sebelumnya sebagaimana mestinya.

Pengingat penting: Java Media Framework adalah API khusus untuk menyinkronkan aliran multimedia (file, aliran jaringan, dan sebagainya). Ini adalah salah satu dari beberapa Java Media API, yang juga mencakup Java 2D, Java 3D, Java Speech, dan sebagainya. Saya merujuk pada Java Media Framework sebagai JMF, menggunakan istilah Java Media untuk seluruh koleksi API multimedia.

Sejarah dan dasar-dasar JMF

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

Java Media Player API, bagian dari Java Media Framework (JMF), memungkinkan programmer Java dengan mudah memasukkan audio dan video ke dalam applet dan aplikasi. Baik multimedia statis dan streaming didukung dari semua URL yang valid. Pemutar JMF dapat dikontrol oleh pemain lain, menyediakan pemutaran sinkron beberapa sampel audio dan video.

Informasi ini masih berlaku dengan pembaruan dan penambahan selama dua tahun terakhir. Namun, JMF telah mengembangkan kapabilitas baru dan berkembang dalam cakupannya, terutama dengan rilis API 2.0 yang akan datang (diharapkan pada paruh kedua tahun 1999).

Pemain industri JMF

Pertama, mari kita lihat para pelaku industri. Sun, Silicon Graphics (SGI), dan Intel merancang dan menetapkan JMF 1.0 asli pada pertengahan 1998. Untuk sementara sejak versi awal API, SGI dan Intel telah menarik diri dari proses spesifikasi JMF. Untuk sementara, komunitas pengguna JMF sangat prihatin bahwa Sun adalah satu-satunya vendor yang mendukung JMF. Situasi ini tidak diinginkan.

Untungnya, pada akhir 1998 IBM ikut campur dengan minat pada JMF. Tak lama setelah IBM bergabung dengan Sun, implementasi semua-Java dari 1.0 API dirilis (Desember 1998). Implementasi ini, yang dikenal sebagai JMF 1.1 untuk platform Java, mendukung subset terbatas namun signifikan dari konten dan jenis protokol yang didukung oleh implementasi Win32 dan Solaris-native JMF 1.1 (dikenal sebagai paket kinerja). Ketersediaan JMF 1.1 yang seluruhnya Java merupakan tonggak penting bagi JMF, karena teknologinya tersedia untuk runtime yang sesuai dengan Java 1.1 atau Java 2. Faktanya, implementasi Java JMF 1.1 bahkan tersedia dalam versi berorientasi Web dengan alat yang memungkinkan pengembang untuk memasukkan hanya kelas JMF yang relevan dalam file JAR untuk diunduh dengan applet JMF mereka. Hal ini memungkinkan seseorang untuk menyebarkan applet berbasis JMF di server Web untuk digunakan oleh browser yang mendukung Java 1.1. Baik Netscape dan Microsoft mendukung Java 1.1 - dan karenanya JMF 1.1 untuk Java - masing-masing dalam rilis browser terbaru mereka dari Navigator dan Internet Explorer.

IBM membantu Sun untuk membuat kode JMF 2.0 API, yang akan menyertakan spesifikasi dan memberikan implementasi referensi untuk JMF API berikutnya: Java Media Capture. Mari berharap IBM akan mencari tahu bagaimana selanjutnya memasukkan fungsionalitas JMF ke dalam beberapa produk perangkat lunak berbasis Java yang berorientasi bisnis - hal yang berpotensi baik untuk umur panjang teknologi JMF.

Apa yang baru di JMF 2.0 vs. 1.0?

JMF 1.0 API menentukan komponen yang diperlukan untuk menangani pemutaran audio dan video yang disinkronkan. Silakan merujuk ke artikel JMF saya sebelumnya (lihat Sumberdaya) untuk review tentang kapabilitas JMF 1.0.

JMF 2.0 membuat beberapa tambahan kunci pada spesifikasi:

  • Perekaman audio dan video
  • Streaming audio dan video, dan dengan demikian kemungkinan membangun server streaming semua-Java selain klien
  • Dukungan codec yang dapat dicolokkan dalam pemain

Untuk informasi lebih lanjut tentang JMF 2.0 dan kapabilitas barunya, silakan merujuk ke Panduan Programmer Java Media Framework (lihat Sumberdaya), yang saat ini tersedia dalam akses awal versi 0.5.

Pemasangan alat pengembangan dan runtime JMF

Baik Silicon Graphics dan Intel telah menghapus versi JMF sebelumnya dari situs web masing-masing. Namun, Anda dapat mengunduh implementasi referensi terbaru (dilambangkan dengan JMF 1.1, sesuai dengan spesifikasi API 1.0) untuk platform Win32, Solaris, dan Java dari situs Sun (lihat Sumberdaya).

Perhatikan bahwa dokumentasi untuk semua versi Java secara khusus menyebutkan AIX, yang menunjukkan bahwa IBM telah menguji perangkat lunak ini pada waktu proses AIX Java-nya. Saya mengharapkan rilis JMF (2.0 dan seterusnya) di masa mendatang untuk secara khusus mendukung lingkungan operasi IBM, baik melalui implementasi Java murni atau implementasi asli khusus OS.

Contoh JMF yang diperbarui

Saya telah memperbarui contoh kepatuhan JMF 1.0 beta dari artikel JMF saya sebelumnya untuk dijalankan di lingkungan yang sesuai dengan JMF 1.0 API. Anda dapat mengunduh kode contoh dan mencobanya pada implementasi JMF 1.1 menggunakan file media Anda sendiri. Applet juga harus berjalan pada runtime JMF 2.0 saat tersedia. (Untuk mengunduh semua file yang terkait dengan artikel ini dalam format zip, lihat Sumber.)

001 // Beri komentar pada pernyataan paket berikut untuk dikompilasi secara terpisah. 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 memperbarui JMFApplet dari artikel JavaWorld April 1997 012 * untuk kepatuhan API JMF 1.1. Harap 013 * lihat artikel di:

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

016 * Selain itu, JMF11Applet telah bekerja ulang ke 017 * menggunakan model peristiwa Java 1.1 (dan seterusnya). Versi 018 * ini telah dikembangkan dan diuji pada Java 2.019 * dan implementasi JMF 1.1 semua-Java, Mei 1999. 020 *

021 * Applet ini dapat digunakan untuk server Web publik 022 * menggunakan jmf-server.jar yang disediakan di JMF 1.1 023 * untuk mengunduh Server Web. Arsip JAR ini berisi 024 * kelas runtime JMF semua-Java yang diperlukan. JMF11Applet 025 * telah digunakan dengan cara ini untuk kolom 026 * Juni 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 public class JMF11Applet extends Applet mengimplementasikan ControllerListener {040 private URL myURL = null; 041 Pemain pribadi myPlayer = null; 042 private Komponen myVisual = null; 043 Komponen pribadi myControls = null; 044 Panel pribadi visualPanel = null; 045 046 / ** 047 * Inisialisasi JMF11Applet. Kami mengatur antarmuka dan 048 * membuat pemutar kami di init (). 049 ** / 050 public void init () {051 super.init (); 052 053 // Tentukan Manajer Tata Letak AWT. 054 setLayout (new BorderLayout ());055 056 // Muat URL dari halaman Web JMF11Applet tertanam. 057 String asset = getParameter ("ASSET"); 058 059 // Periksa URL dan buat objek URL untuk menampungnya. 060 if (asset.equals ("")) {061 // kita belum memasukkan aset ke applet. 062} lain {063 coba {064 myURL = URL baru (getDocumentBase (), aset); 065} catch (MalformedURLException e) {066 // Kami memasukkan aset yang tidak lengkap atau membuat URL yang salah. 067 // Applet yang lebih kuat harus menangani ini dengan baik. 068} 069} 070 coba {071 // Ini sedikit menarik. Manajer digunakan untuk 072 // membuat pemutar sebenarnya untuk URL ini. Kemudian 073 // tambahkan JMF11Applet sebagai ControllerListener untuk myPlayer. 074 // Ini memungkinkan kita menanggapi RealizeCompleteEvents. 075 myPlayer = Manager.createPlayer (myURL); 076 myPlayer.addControllerListener (ini);077} catch (IOException e) {078 // Mengalami beberapa masalah dengan I / O; keluar. 079 System.out.println ("Masalah I / O saat mencoba membuat pemutar ... keluar"); 080 System.exit (1); 081} catch (NoPlayerException e) {082 // Tak dapat mengembalikan Player yang bisa digunakan; keluar. 083 System.out.println ("Tidak ada Pemutar yang dapat digunakan kembali ... keluar"); 084 System.exit (1); 085} 086} 087 088 / ** 089 * Timpa metode applet start default untuk memanggil Player's 090 * menyadari (). Ini pertama-tama akan melakukan realisasi, yang pada gilirannya 091 * memicu bit terakhir dari bangunan GUI dalam metode controllerUpdate () 092 *. Kami tidak memulai pemutaran secara otomatis: Pengguna memerlukan 093 * untuk mengklik tombol "putar" di applet kami untuk mulai memutar sampel media 094 *. 095 ** / 096 public void start () {097 myPlayer.realize ();098} 099 100 101 / ** 102 * Ganti metode applet stop default untuk memanggil myPlayer.stop () 103 * dan myPlayer.deallocate () sehingga kami mengosongkan sumber daya 104 * dengan benar jika seseorang keluar dari halaman ini di browser mereka. 105 ** / 106 public void stop () {107 myPlayer.stop (); 108 myPlayer.deallocate (); 109} 110 111 / ** 112 * Karena kita harus tahu kapan realisasi selesai, kita menggunakan 113 * controllerUpdate () untuk menangani RealizeCompleteEvents. 114 * Saat kami menerima RealizeCompleteEvent, kami membuat layout 115 * dan menampilkan komponen video dan kontrol dalam GUI applet 116 * kami. 117 ** / 118 public void controllerUpdate (event ControllerEvent) {119 if (event instanceof RealizeCompleteEvent) {120 //System.out.println("Received RCE ... "); 121 // Sekarang kita memiliki pemain Realized,kita bisa mendapatkan 122 // VisualComponent dan ControlPanelComponent dan mengemas 123 // ke dalam applet kita. 124 myVisual = myPlayer.getVisualComponent (); 125 if (myVisual! = Null) {126 // Untuk memastikan bahwa VisualComponent 127 // tidak diubah ukurannya oleh BorderLayout, saya menumpuknya 128 // dalam visualPanel menggunakan FlowLayout. 129 visualPanel = Panel baru (); 130 visualPanel.setLayout (FlowLayout baru ()); 131 visualPanel.add (myVisual); 132 tambahkan (visualPanel, BorderLayout.CENTER); 133 //System.out.println("Added VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 jika (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("Kontrol yang ditambahkan ... "); 139} 140 // invalidate (); 141 validasi (); 142} 143 // Jika tidak, kita cukup mengonsumsi acara tersebut. 144} 145}124 myVisual = myPlayer.getVisualComponent (); 125 if (myVisual! = Null) {126 // Untuk memastikan bahwa VisualComponent 127 // tidak diubah ukurannya oleh BorderLayout, saya menumpuknya 128 // dalam visualPanel menggunakan FlowLayout. 129 visualPanel = Panel baru (); 130 visualPanel.setLayout (FlowLayout baru ()); 131 visualPanel.add (myVisual); 132 tambahkan (visualPanel, BorderLayout.CENTER); 133 //System.out.println("Added VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 jika (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("Kontrol yang ditambahkan ... "); 139} 140 // invalidate (); 141 validasi (); 142} 143 // Jika tidak, kita cukup mengonsumsi acara tersebut. 144} 145}124 myVisual = myPlayer.getVisualComponent (); 125 if (myVisual! = Null) {126 // Untuk memastikan bahwa VisualComponent 127 // tidak diubah ukurannya oleh BorderLayout, saya menumpuknya 128 // dalam visualPanel menggunakan FlowLayout. 129 visualPanel = Panel baru (); 130 visualPanel.setLayout (FlowLayout baru ()); 131 visualPanel.add (myVisual); 132 tambahkan (visualPanel, BorderLayout.CENTER); 133 //System.out.println("Added VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 jika (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("Kontrol yang ditambahkan ... "); 139} 140 // invalidate (); 141 memvalidasi (); 142} 143 // Jika tidak, kita cukup mengonsumsi acara tersebut. 144} 145}= null) {126 // Untuk memastikan bahwa VisualComponent 127 // tidak diubah ukurannya oleh BorderLayout, saya menumpuknya 128 // dalam visualPanel menggunakan FlowLayout. 129 visualPanel = Panel baru (); 130 visualPanel.setLayout (FlowLayout baru ()); 131 visualPanel.add (myVisual); 132 tambahkan (visualPanel, BorderLayout.CENTER); 133 //System.out.println("Added VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 jika (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("Kontrol yang ditambahkan ... "); 139} 140 // invalidate (); 141 validasi (); 142} 143 // Jika tidak, kita cukup mengonsumsi acara tersebut. 144} 145}= null) {126 // Untuk memastikan bahwa VisualComponent 127 // tidak diubah ukurannya oleh BorderLayout, saya menyarangkannya 128 // dalam visualPanel menggunakan FlowLayout. 129 visualPanel = Panel baru (); 130 visualPanel.setLayout (FlowLayout baru ()); 131 visualPanel.add (myVisual); 132 tambahkan (visualPanel, BorderLayout.CENTER); 133 //System.out.println("Added VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 jika (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("Kontrol yang ditambahkan ... "); 139} 140 // invalidate (); 141 memvalidasi (); 142} 143 // Jika tidak, kita cukup mengonsumsi acara tersebut. 144} 145}133 //System.out.println("Added VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 jika (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("Kontrol yang ditambahkan ... "); 139} 140 // invalidate (); 141 validasi (); 142} 143 // Jika tidak, kita cukup mengonsumsi acara tersebut. 144} 145}133 //System.out.println("Added VisualComponent ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 jika (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("Kontrol yang ditambahkan ... "); 139} 140 // invalidate (); 141 memvalidasi (); 142} 143 // Jika tidak, kita cukup mengonsumsi acara tersebut. 144} 145}

Saya telah menyertakan contoh dokumen HTML sederhana, example.html (yang dapat Anda coba di browser Anda sekarang dengan mengklik di sini), untuk menunjukkan kepada Anda cara menyematkan applet ke halaman Web Anda sendiri. Cukup ubah file media di ASSETtag dan pergilah!

Untuk contoh ini, saya menggunakan JMF 1.1 untuk pengunduhan Server Web (didokumentasikan di situs Web JMF) untuk mengaktifkan JMF11Appletpengunduhan otomatis jmf-server.jar, arsip kode yang berisi kelas runtime JMF yang diperlukan. Hal ini memungkinkan applet untuk mengeksekusi dalam browser yang kompatibel dengan Java 1.1, tanpa perangkat lunak untuk dipasang oleh pengguna akhir. (Perhatikan bahwa versi JMF untuk Server Web juga menyertakan alat kustomisasi JMFCustomizer, yang berpotensi memungkinkan Anda menghapus lebih banyak kelas yang tidak diperlukan dari file JMF JAR. Namun, alat ini saat ini tidak berfungsi di bawah Java 2, karena menggunakan nama paket untuk Swing.)

Dalam contoh khusus yang disematkan di example.html , kami memuat file WAV (welcome.wav), memastikan komponen kontrol yang sesuai untuk disediakan (tidak ada komponen video, karena ini adalah file media khusus suara), dan memutar multimedia mengajukan. Perhatikan bahwa file WAV (600 KB) dan kelas JMF (570 KB) mungkin memerlukan beberapa menit untuk diunduh ke mesin Anda tergantung pada kecepatan koneksi Anda.

Setelah parsing halaman contoh, browser yang mendukung Java 1.1 harus memuat applet dan mendukung kelas JMF secara otomatis dari server Web JavaWorld . Setelah applet dimuat dan dijalankan, Anda dapat menekan tombol Putar untuk memulai pemutaran file suara WAV. Coba ubah posisi pemutaran menggunakan bilah gulir dan jeda dan mulai ulang pemutaran menggunakan tombol Jeda / Putar.

Implementasi platform Java JMF 1.1 menggunakan semua widget Java untuk kontrolnya, sehingga kontrol tersebut memiliki tampilan yang sama dari browser ke browser dan platform ke platform. Perhatikan bagaimana applet terlihat berjalan dalam JVM Netscape Communicator pada Solaris 7 dan JVM Microsoft pada Internet Explorer pada Win32.

Tombol berlabel i memberikan informasi tentang file media yang diputar di applet JMF. Klik link informasi ini untuk mendapatkan rincian file WAV yang berjalan di halaman Web ini.