Java媒體框架(Java Media Framework,JMF)作為Java平台的多媒體處理標準API,雖然歷史久遠,但其跨平台、可擴展的架構設計至今仍具參考價值。本文將深度解析基於JMF設計自動播放器的核心原理、關鍵技術難點及實戰方案,特別關注如何將解碼器與媒體內容打包為可自播放的JAR文件。
JMF的Manager默認只識別標準協議(file、http等)和常見文件擴展名。對於JAR包內的媒體資源(如jar:file:/path/app.jar!/media/video.mp4),Manager無法識別jar:協議,導致無法找到合適的DataSource和Player。
實現自定義DataSource(繼承PullDataSource),核心任務:
PullDataSource接口:getStreams()、start()、stop()等PullSourceStream接口:read()、getContentType()、getContentLength()等Seekable接口(可選):支持隨機訪問seek()、tell()
public String getContentType() {
try {
URL url = getLocator().getURL();
String urlFile = url.getFile();
if (urlFile.endsWith(".mov")) return "video.quicktime";
else if (urlFile.endsWith(".mpg")) return "video.mpeg";
else if (urlFile.endsWith(".avi")) return "video.x_msvideo"; // 注意下劃線
else return "unknown";
} catch (MalformedURLException e) {
return "unknown";
}
}
public long seek(long position) {
try {
if (position > tellPoint) {
thoroughSkip(position - tellPoint);
} else {
close();
open();
thoroughSkip(position);
}
return tellPoint;
} catch (IOException ioe) {
return 0;
}
}
private void thoroughSkip(long n) throws IOException {
long skipped = 0;
while (skipped < n) {
long skippedThisTime = inputStream.skip(n - skipped);
if (skippedThisTime == 0) break;
skipped += skippedThisTime;
}
tellPoint += skipped;
}
autoplayer.jar ├── META-INF/ │ └── MANIFEST.MF # Main-Class, Class-Path ├── com/ │ └── myplayer/ │ ├── PlayerApp.class # 主類 │ └── datasource/ # 自定義DataSource實現 ├── media/ │ └── movie.mp4 # 媒體資源 └── javax/media/... # 精簡JMF類
Manifest-Version: 1.0
Main-Class: com.myplayer.PlayerApp
Class-Path: . jmf.jar
public class PlayerApp {
public static void main(String[] args) {
// 註冊自定義協議處理器(可選)
URL.setURLStreamHandlerFactory(new JarProtocolHandlerFactory());
// 構建媒體URL
String mediaPath = "media/movie.mp4";
URL mediaUrl = PlayerApp.class.getResource(mediaPath);
// 創建Player
Player player = Manager.createRealizedPlayer(mediaUrl);
// 獲取視覺/控制組件
Component visual = player.getVisualComponent();
Component control = player.getControlPanelComponent();
// 構建UI
JFrame frame = new JFrame("Auto Player");
frame.setLayout(new BorderLayout());
if (visual != null) frame.add(visual, BorderLayout.CENTER);
if (control != null) frame.add(control, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
player.start();
}
}
JAR協議需要註冊URLStreamHandlerFactory,或使用ClassLoader.getResource()獲取JAR內資源URL。JDK 1.2+支持jar:協議,但需正確註冊。
QuickTime Player要求DataSource實現Seekable接口。實現seek()、tell()、getContentLength(),內部使用InputStream.skip()或重新打開流實現隨機訪問。
根據文件擴展名返回MIME類型(點號替換斜線),如video/quicktime→video.quicktime,供Manager查找解碼器包。
java -jar autoplay.jar基於JMF設計自動播放器的核心在於:自定義DataSource支持JAR協議、實現Seekable接口、正確映射內容類型、構建輕量級運行時。雖然JMF已停止更新,但其架構思想對理解媒體播放架構仍有重要參考價值。現代替代方案包括JavaFX Media、VLCJ、FFmpeg Java綁定等。