התקדמות בממשקי ה- API של JMF ו- Java Media

המאמר הראשון שלי ב- JavaWorld היה דרך ה- Java Media Framework (JMF). עם התבגרותם של ממשקי ה- API השונים של מדיה, אני מרגיש שהדברים עברו מעגל מלא. לכן אקדיש את העמודה הסופית שלי לתכנות מדיה לביקור חוזר של JMF ולמצב הכללי של כל ממשקי ה- API של Java Media.

היו שינויים בולטים ב- JMF ובטכנולוגיות Java Media אחרות, חברות המפתחות יישומים שלהן וזמינותן למפתחים. מאמר זה מעדכן את החומר ממאמרים קודמים לפי הצורך.

תזכורת חשובה: Java Media Framework הוא ממשק API ספציפי לסנכרון זרמי מולטימדיה (קבצים, זרמי רשת וכדומה). זהו אחד מכמה ממשקי ה- API של Java Media, הכוללים גם Java 2D, Java 3D, Java Speech, וכן הלאה. אני מתייחס ל- Java Media Framework כ- JMF, ושומר את המונח Java Media לכל אוסף ממשקי ה- API של מולטימדיה.

היסטוריית יסודות הקק"ל

מתוך ה- JMF 1.0, המכונה API של נגן המדיה של Java, כתבתי את הדברים הבאים באפריל 1997 (ראה משאבים):

ממשק ה- API של Java Media Player, חלק ממסגרת ה- Java Media Framework (JMF), מאפשר למתכנתי Java להטמיע אודיו ווידאו בקלות ביישומונים ויישומים. גם מולטימדיה סטטית וגם סטרימינג זורם נתמכים מכל כתובת URL חוקית. נגני JMF עשויים להיות נשלטים על ידי נגנים אחרים, ומספקים הפעלה סינכרונית של מספר דגימות שמע ווידאו.

מידע זה עדיין נכון עם העדכונים והתוספות של השנתיים האחרונות. JMF, לעומת זאת, פיתחה יכולות חדשות וגדלה בהיקפן, במיוחד עם מהדורת 2.0 API הקרובה (צפויה במחצית השנייה של 1999).

שחקני תעשיית ה- JMF

ראשית, בואו נסתכל על שחקני התעשייה. סאן, גרפיקה מסיליקון (SGI) ואינטל תכננו וציינו את ה- JMF 1.0 המקורי באמצע שנת 1998. בינתיים מאז הגרסה הראשונית של ה- API, הן SGI והן אינטל פרשו מתהליך המפרט של JMF. במשך זמן מה, היה חשש משמעותי בקהילת המשתמשים ב- JMF כי סאן היא הספקית היחידה שתומכת ב- JMF. מצב זה לא היה רצוי.

למרבה המזל, בסוף שנת 1998 יבמ נכנסה להתעניינות ב- JMF. זמן קצר לאחר שחברת IBM הצטרפה ל- Sun, פורסם יישום של כל ה- Java של ה- API 1.0 (דצמבר 1998). יישום זה, המכונה JMF 1.1 לפלטפורמות Java, תומך בקבוצת משנה מוגבלת אך משמעותית של סוגי התוכן והפרוטוקול הנתמכים ביישומי JMF 1.1 המקוריים Win32 ו- Solaris (המכונים חבילות ביצועים.). הזמינות של JMF 1.1 לכל Java הייתה אבן דרך מרכזית עבור JMF, בכך שהטכנולוגיה הפכה לזמינה לכל זמן ריצה תואם Java 1.1 או Java 2. למעשה, יישום ה- JMF 1.1 Java זמין אפילו בגרסה מכוונת אינטרנט עם כלים המאפשרים למפתחים לכלול רק את מחלקות ה- JMF הרלוונטיות בקובץ JAR להורדה עם יישומי ה- JMF שלהם. זה מאפשר לפרוס יישומונים מבוססי JMF בשרת אינטרנט לשימוש על ידי כל דפדפן תואם Java 1.1. הן נטסקייפ והן מיקרוסופט תומכות בג'אווה 1.1 - ולכן JMF 1.1 בג'אווה - במהדורות הדפדפן האחרונות שלהן של Navigator ו- Internet Explorer, בהתאמה.

יבמ מסייעת ל- Sun להגדיר קידוד את ממשק ה- API של JMF 2.0, שיכלול מפרט ויספק יישום הפניה של ה- API הבא של JMF: Java Media Capture. נקווה שיבמ תבין כיצד לאחר מכן לגלגל פונקציונליות של JMF לחלק ממוצרי התוכנה מבוססי הג'אווה שלה - דבר שעשוי להיות טוב לאורך החיים של טכנולוגיית JMF.

מה חדש ב- JMF 2.0 לעומת 1.0?

ה- API של JMF 1.0 מציין את הרכיבים הדרושים לטיפול בהפעלה של אודיו ווידאו מסונכרנים. אנא עיין במאמר הקודם של JMF (ראה משאבים) לבדיקת יכולות ה- JMF 1.0.

JMF 2.0 מבצע מספר תוספות מפתח למפרט:

  • צילום אודיו ווידאו
  • הזרמת שמע ווידאו, ובכך אפשרות לבנות שרתי סטרימינג של כל Java בנוסף ללקוחות
  • תמיכה ב- Codec הניתנת לחיבור בקרב שחקנים

למידע נוסף על JMF 2.0 והיכולות החדשות שלו, עיין במדריך למתכנת Java Media Framework (ראה משאבים), זמין כעת בגישה מוקדמת בגירסה 0.5.

התקנת כלי פיתוח JMF וזמן ריצה

גם סיליקון גרפיקה וגם אינטל הסירו גרסאות קודמות של JMF מאתרי האינטרנט שלהם. עם זאת, תוכל להוריד את יישומי הייחוס האחרונים (המסומנים JMF 1.1, תואמים למפרט 1.0 API) לפלטפורמות Win32, Solaris ו- Java מאתר Sun (ראה משאבים).

שים לב כי בתיעוד של גרסת ה- Java הכוללת מוזכר AIX באופן ספציפי, המצביע על כך ש- IBM בדקה תוכנה זו בזמן הריצה של AIX Java. אני מצפה שפרסומים עתידיים של ה- JMF (2.0 ואילך) יתמכו באופן ספציפי בסביבות הפעלה של IBM, בין אם באמצעות יישום טהור של Java או יישומים מקוריים ספציפיים למערכת הפעלה.

דוגמאות JMF מעודכנות

עדכנתי את הדוגמה התואמת ל- JMF 1.0 ממאמר ה- JMF הקודם שלי להפעלה בסביבות תואמות API ל- JMF 1.0. אתה יכול להוריד את קוד הדוגמה ולנסות אותו תחת יישומי JMF 1.1 באמצעות קבצי מדיה משלך. היישומון אמור לפעול גם בשעות הפעלה של JMF 2.0 כאשר הם יהיו זמינים. (כדי להוריד את כל הקבצים המשויכים למאמר זה בפורמט zip, ראה משאבים.)

001 // הגב את הצהרת החבילה הבאה כדי להרכיב בנפרד. 002 // חבילה com.javaworld.media.jmf; 003 004 ייבא java.applet. *; 005 ייבוא ​​java.awt. *; 006 ייבא java.net. *; 007 יבוא java.io. *; 008 ייבוא ​​javax.media. *; 009 010 / ** 011 * JMF11Applet מעדכן את JMFApplet ממאמר אפריל 1997 012 * מאמר JavaWorld לתאימות JMF 1.1 API. אנא 013 * עיין במאמר בכתובת:

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

016 * בנוסף, JMF11Applet עבד מחדש כדי 017 * להשתמש במודל האירועים Java 1.1 (ומעבר לכך). גרסת 018 * זו פותחה ונבדקה ב- Java 2 019 * וביישום JMF 1.1 כל Java, מאי 1999. 020 *

021 * יישומון זה עשוי להתפרס על שרתי אינטרנט ציבוריים 022 * באמצעות jmf-server.jar המסופק ב- JMF 1.1 023 * להורדת שרתי אינטרנט. ארכיב JAR זה מכיל 024 * שיעורי זמן הריצה הדרושים ל- JMF לכל Java. JMF11Applet 025 * נפרס באופן זה בעמודה 026 * ביוני 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 מחלקה ציבורית JMF11 Applet מתארך היישומון מיישם את ControllerListener {040 כתובת אתר פרטית myURL = null; 041 נגן פרטי myPlayer = null; 042 רכיב פרטי myVisual = null; 043 רכיב פרטי myControls = null; 044 לוח פרטי visualPanel = null; 045 046 / ** 047 * אתחל את JMF11 היישומון. אנו פורשים את הממשק ו 048 * יוצרים את הנגן שלנו ב- init (). 049 ** / 050 init חלל ציבורי () {051 super.init (); 052 053 // ציין את מנהל הפריסה של AWT. 054 setLayout (BorderLayout חדש ());055 056 // טען כתובת אתר מדף האינטרנט JMF11Applet מוטבע בתוכנה. 057 נכס מחרוזת = getParameter ("ASSET"); 058 059 // בדוק את כתובת האתר וצור אובייקט URL כדי להחזיק אותו. 060 if (asset.equals ("")) {061 // לא הזנו נכס ביישומון. 062} אחר {063 נסה {064 myURL = URL חדש (getDocumentBase (), נכס); 065} לתפוס (MalformedURLException e) {066 // הזנו נכס לא שלם או בנינו כתובת אתר שגויה. 067 // יישומון חזק יותר צריך להתמודד עם זה בחן. 068} 069} 070 נסה {071 // הנה קצת מעניין. מנהל משמש 072 // ליצור את השחקן בפועל עבור כתובת אתר זו. לאחר מכן אנו 073 // מוסיפים את JMF11Applet כ- ControllerListener עבור myPlayer. 074 // זה מאפשר לנו להגיב ל- RealizeCompleteEvents. 075 myPlayer = Manager.createPlayer (myURL); 076 myPlayer.addControllerListener (זה);077} לתפוס (IOException e) {078 // נתקל בבעיה כלשהי עם קלט / פלט; יְצִיאָה. 079 System.out.println ("בעיית קלט / פלט בניסיון ליצור נגן ... יוצאת"); 080 System.exit (1); 081} לתפוס (NoPlayerException e) {082 // לא ניתן להחזיר נגן שמיש; יְצִיאָה. 083 System.out.println ("לא הוחזר נגן שמיש ... יוצא"); 084 System.exit (1); 085} 086} 087 088 / ** 089 * עקף את שיטת ברירת המחדל של התחלת היישומון כדי להתקשר ל 090 * של Player (real). תחילה זה יבצע את המימוש, אשר בתורו 091 * מפעיל את החלקים האחרונים של בניית ה- GUI בשיטת controllerUpdate () 092 *. אנו לא מתחילים את ההשמעה באופן אוטומטי: המשתמש זקוק ל- 093 * כדי ללחוץ על כפתור ה"הפעלה "ביישומון שלנו כדי להתחיל לנגן את מדגם המדיה 094 *. 095 ** / 096 התחלה בטלנית ציבורית () {097 myPlayer.realize ();098} 099 100 101 / ** 102 * עקוף את שיטת ברירת המחדל של עצירת היישומון להתקשר ל- myPlayer.stop () 103 * ו- myPlayer.deallocate () כך שנפנה כראוי משאבים 104 * אם מישהו יוצא מדף זה בדפדפן שלו. 105 ** / 106 עצירת חלל ציבורית () {107 myPlayer.stop (); 108 myPlayer.deallocate (); 109} 110 111 / ** 112 * מכיוון שעלינו לדעת מתי השלמת המימוש, אנו משתמשים ב- 113 * controllerUpdate () כדי לטפל ב- RealizeCompleteEvents. 114 * כשאנחנו מקבלים את RealizeCompleteEvent, אנו מתכננים 115 * ומציגים את רכיב הווידאו והפקדים בממשק המשתמש של יישומון 116 *. 117 ** / 118 בקר חלל ציבורי Update (אירוע ControllerEvent) {119 אם (מופע אירוע של RealizeCompleteEvent) {120 //System.out.println("RCEived ... "); 121 // עכשיו שיש לנו שחקן ממומש,נוכל להשיג את 122 // VisualComponent ו- ControlPanelComponent ולארוז 123 // אותם ביישומון שלנו. 124 myVisual = myPlayer.getVisualComponent (); 125 if (myVisual! = Null) {126 // על מנת להבטיח שגודל VisualComponent 127 // לא ישונה על ידי BorderLayout, אני מקנן אותו 128 // בתוך visualPanel באמצעות FlowLayout. 129 visualPanel = פאנל חדש (); 130 visualPanel.setLayout (FlowLayout חדש ()); 131 visualPanel.add (myVisual); 132 הוסף (visualPanel, BorderLayout.CENTER); 133 // System.out.println(" VisualComponent נוסף ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 if (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("בקרות נוספות ... "); 139} 140 // לפסול (); 141 לאמת (); 142} 143 // אחרת אנחנו פשוט צורכים את האירוע. 144} 145}124 myVisual = myPlayer.getVisualComponent (); 125 if (myVisual! = Null) {126 // על מנת להבטיח שגודל VisualComponent 127 // לא ישונה על ידי BorderLayout, אני מקנן אותו 128 // בתוך visualPanel באמצעות FlowLayout. 129 visualPanel = פאנל חדש (); 130 visualPanel.setLayout (FlowLayout חדש ()); 131 visualPanel.add (myVisual); 132 הוסף (visualPanel, BorderLayout.CENTER); 133 // System.out.println(" VisualComponent נוסף ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 if (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("בקרות נוספות ... "); 139} 140 // לפסול (); 141 לאמת (); 142} 143 // אחרת אנחנו פשוט צורכים את האירוע. 144} 145}124 myVisual = myPlayer.getVisualComponent (); 125 if (myVisual! = Null) {126 // על מנת להבטיח שגודל VisualComponent 127 // לא ישונה על ידי BorderLayout, אני מקנן אותו 128 // בתוך visualPanel באמצעות FlowLayout. 129 visualPanel = פאנל חדש (); 130 visualPanel.setLayout (FlowLayout חדש ()); 131 visualPanel.add (myVisual); 132 הוסף (visualPanel, BorderLayout.CENTER); 133 // System.out.println(" VisualComponent נוסף ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 if (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("בקרות נוספות ... "); 139} 140 // לפסול (); 141 לאמת (); 142} 143 // אחרת אנחנו פשוט צורכים את האירוע. 144} 145}= null) {126 // כדי להבטיח שגודל VisualComponent 127 // לא ישתנה על ידי BorderLayout, אני מקנן אותו 128 // בתוך visualPanel באמצעות FlowLayout. 129 visualPanel = פאנל חדש (); 130 visualPanel.setLayout (FlowLayout חדש ()); 131 visualPanel.add (myVisual); 132 להוסיף (visualPanel, BorderLayout.CENTER); 133 // System.out.println(" VisualComponent נוסף ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 if (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("בקרות נוספות ... "); 139} 140 // לפסול (); 141 לאמת (); 142} 143 // אחרת אנחנו פשוט צורכים את האירוע. 144} 145}= null) {126 // על מנת להבטיח שגודל VisualComponent 127 // לא ישונה על ידי BorderLayout, אני מקנן אותו 128 // בתוך visualPanel באמצעות FlowLayout. 129 visualPanel = פאנל חדש (); 130 visualPanel.setLayout (FlowLayout חדש ()); 131 visualPanel.add (myVisual); 132 הוסף (visualPanel, BorderLayout.CENTER); 133 // System.out.println(" VisualComponent נוסף ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 if (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("בקרות נוספות ... "); 139} 140 // לפסול (); 141 לאמת (); 142} 143 // אחרת אנחנו פשוט צורכים את האירוע. 144} 145}133 // System.out.println(" VisualComponent נוסף ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 if (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("בקרות נוספות ... "); 139} 140 // לפסול (); 141 לאמת (); 142} 143 // אחרת אנחנו פשוט צורכים את האירוע. 144} 145}133 // System.out.println(" VisualComponent נוסף ... "); 134} 135 myControls = myPlayer.getControlPanelComponent (); 136 if (myControls! = Null) {137 add (myControls, BorderLayout.SOUTH); 138 //System.out.println("בקרות נוספות ... "); 139} 140 // לפסול (); 141 לאמת (); 142} 143 // אחרת אנחנו פשוט צורכים את האירוע. 144} 145}

צירפתי מסמך HTML פשוט לדוגמא, example.html (שתוכל לנסות בדפדפן שלך עכשיו על ידי לחיצה כאן), כדי להראות לך כיצד להטמיע את היישומון בדפי האינטרנט שלך. כל שעליך לעשות הוא לשנות את קובץ המדיה ASSETבתג ולצאת לדרך!

לדוגמא זו השתמשתי בהורדת שרתי האינטרנט JMF 1.1 (מתועד באתר האינטרנט של JMF) כדי לאפשר JMF11Appletהורדה אוטומטית jmf-server.jar, ארכיון קוד המכיל את שיעורי הריצה הדרושים של JMF. זה מאפשר ליישומון לבצע בכל דפדפן תואם Java 1.1, ללא תוכנה להתקנת משתמש הקצה. (שים לב שגרסת JMF לשרתי אינטרנט כוללת גם כלי התאמה אישית,, JMFCustomizerאשר עלול לאפשר לך להסיר עוד יותר מחלקות לא נחוצות מקובץ JMF JAR. כלי זה אינו פועל כרגע תחת Java 2, אולם מכיוון שהוא משתמש במיושן מיושן. שם חבילה עבור Swing.)

בדוגמה המסוימת המוטמעת ב- example.html , אנו טוענים קובץ WAV (welcome.wav), נבדוק את רכיבי הבקרה המתאימים להנגשה (ללא רכיב וידיאו, מכיוון שמדובר בקובץ מדיה צליל בלבד) ומשמיעים את המולטימדיה. קוֹבֶץ. שים לב שקובץ WAV (600 KB) ושיעורי JMF (570 KB) עשויים לארוך מספר דקות להורדה למכשיר שלך, בהתאם למהירות החיבור שלך.

לאחר הניתוח של דף הדוגמה, דפדפנים תואמי Java 1.1 צריכים לטעון את היישומון ולתמוך בכיתות JMF באופן אוטומטי משרת האינטרנט JavaWorld . לאחר טעינת היישומון והפעלתו, תוכלו ללחוץ על כפתור ההפעלה כדי להתחיל בהשמעה של קובץ הצליל WAV. נסה למקם את ההפעלה מחדש באמצעות סרגל הגלילה ולהשהות ולהפעיל מחדש את ההפעלה באמצעות לחצן Pause / Play.

יישום פלטפורמת Java JMF 1.1 משתמש בווידג'טים של כל Java לצורך בקרתו, כך שהפקדים הם בעלי מראה זהה מדפדפן לדפדפן ופלטפורמה לפלטפורמה. שימו לב איך נראה היישומון פועל בתוך JVM של Netscape Communicator ב- Solaris 7 ו- JVM של מיקרוסופט ב- Internet Explorer ב- Win32.

הכפתור שכותרתו i מספק מידע על קובץ המדיה המושמע ביישומון JMF. לחץ על קישור מידע זה לקבלת פרטים על קובץ ה- WAV הפועל בדף אינטרנט זה.