摘要:
quicktime 视频文件播放程序如今已经发展和成长15年了,在添加新特性的同时也保持了极好的向后兼容性:1990年在系统6或7上制造的quicktime movie2005年仍然能在mac 操作系统x 10.3.7上播放。这是因为quicktime 的共享代码片段的组件系统可被发现和被动态的调用。quicktime 所需要用来播放movie的大部分是一个组件:理解文件格式的代码;使在文件中使用的音频,视频,或其他编解码器减压的代码;处理流媒体协议的代码;等等。旧的组件简单的维护,新的组件向quicktime 添加了更多的功能。当quicktime 的一个新版本增加了对新的格式或编解码器的支持,或当用户自己安装了新的特性,一个运行良好的应用程序将会自动增加这些新的特性。并且,幸运地,组件为java 程序员做好了准备,他们可以使用适合于java 应用编程接口的quicktime 。
在这篇来自《适用于java的quicktime :开发者的宝典》,chris adamson 指出怎么写这样一个性质良好的应用程序。第四章:用组件工作介绍了组件的类型和子类型的识别模式并指出如何导出一个quicktime movie到固定格式,或运行时能找到的任何格式。它说明了如何导入导出图形,并提供了显示所有已安装组件的一个实用程序。
版权声明:任何获得matrix授权的网站,转载时请务必保留以下作者信息和链接
作者:chris adamson;amydeng(作者的blog:http://blog.matrix.org.cn/page/amydeng)
译文:http://www.matrix.org.cn/resource/article/44/44269_java+quicktime.html
关键字:java;quicktime
用组件工作
当quicktime1990年问世的时候,它能够播放一张邮票大小的movie——仅仅在价值7000美圆的硬盘上。它使用音频和视频的编解码器,尽管这些编解码器今天仍然被支持,但已被用户淘汰很久了。然而,从 apple 视频到cinepak 视频再到mpeg-4,是一个平滑的变换。这是由于一个特别的标准化设计——quicktime 里大部分繁重的任务都是由组件或共享的动态代码执行。组件提供了如下的支持:导入导出图片和movie格式,执行图片和声音的压缩和解压缩,访问系统资源及更多其它功能。quicktime安装程序提供了很多组件,这些组件具备许多有效的特性,而用户也可以自己从apple或者第三方添加其他组件进来,这些组件能够提供更多的功能,如支持更多的多媒体格式。
api里组件并不处于中心位置——毕竟,在开始的几章里已经设法完全避免提到它们。当我们需要打开文件并将它们转换为movie,解压缩和解释数据,保存它们到硬盘等等时,这个时候我们quicktime做正确的事情。当需要的时候,quicktime为了必需的功能浏览它的组件目录并得到它所需要的东西。
但是有些时候开发者为了指出什么是可用的,或者为了指定特定地行为,或者需要更直接地使用组件。这个时候, 找出运行时可用的工具是一个强有力的方法。
指定组件类型
quicktime里,组件由类型和子类型来识别,类型指定了功能范围,子类型是该功能的一个特定实现。例如,有一个“movie 导出器”类型,代表可以导出一部movie到非quicktime格式的组件。它用子类型确定适合avi(video for windows 的多媒体文件格式),mpeg-4的导出器, 这些标识符是32比特的整型值,但它们不列举你可能期望来自java的常数。通常地,32比特被分成是4个8比特的ascii 字符来读取,组成一个简短的,易读的名字。这些在本地api包里定义为ostypes类型,但是当与有意义的值组装到一起时,它们被称为“四字符代码”,来自本地four_char_code函数,该函数为一个字符串返回一个ostype类型。这经常简称为 fcc或4cc。
这种模式采纳了c程序员的观点。例如,为一部movie定义4cc需要一个好的,简单的短语,就像在本地页眉文件movies.h 中所见的一样: movieresourcetype = 'moov' 然而,由于java的更先进的文本处理方法,在java中用4ccs 处理要困难的多。因为,unicode的应用意味着每个 java字符是2个比特,这说明我们需要额外的帮助来将java字符转化为4cc。
我们如何做呢?
幸运地,qtutils类提供了2个方法:toostype()和fromostype()。例4-1展示了这些方法,将一个java 字符串转化为一个4cc 表示,并从它的4cc 表示转化回来。
example 4-1. converting to and from four_char_codes
package com.oreilly.qtjnotebook.ch04;
import quicktime.util.qtutils;
public class fourcharcodetest extends object {
public static void main (string[] args) {
if (args.length < 1) {
system.out.println ("usage: fourcharcodetest <fcc>");
return;
}
system.out.println (args[0])
int fcc = qtutils.toostype (args[0]);
system.out.println (fcc);
system.out.println (integer.tohexstring (fcc));
string fccstring = qtutils.fromostype(fcc);
system.out.println (fccstring);
}
}
package com.oreilly.qtjnotebook.ch04;
import quicktime.*;
import quicktime.std.*;
import quicktime.std.movies.*;
import quicktime.io.*;
import quicktime.std.qtcomponents.*;
import quicktime.utils.qtutils;
import java.awt.*;
import javax.swing.*;
import com.oreilly.qtjnotebook.ch01.qtsessioncheck;
public class simplemovieexport extends object {
public static final void main (string[] args) {
new simplemovieexport();
}
public simplemovieexport() {
// build choices
exportchoice[] choices = new exportchoice[3];
choices[0] =
new exportchoice ("quicktime movie",
stdqtconstants.kqtfiletypemovie);
choices[1] =
new exportchoice ("avi file",
stdqtconstants.kqtfiletypeavi);
choices[2] =
new exportchoice ("mpeg-4 file",
qtutils.toostype("mpg4"));
try {
// query user for a movie to open
qtsessioncheck.check();
qtfile file =
qtfile.standardgetfilepreview (qtfile.kstandardqtfiletypes);
openmoviefile omfile = openmoviefile.asread (file);
movie movie = movie.fromfile (omfile);
// offer a choice of movie exporters
jcombobox exportcombo = new jcombobox (choices);
joptionpane.showmessagedialog (null,
exportcombo,
"choose exporter",
joptionpane.plain_message);
exportchoice choice = (exportchoice) exportcombo.getselecteditem();
// create an exporter
movieexporter exporter = new movieexporter (choice.subtype);
qtfile savefile =new qtfile (new java.io.file("untitled"));
// do the export
movie.setprogressproc();
movie.converttofile (null,
savefile,
stdqtconstants.kqtfiletypemovie,
stdqtconstants.kmovieplayer,
ioconstants.smsystemscript,
stdqtconstants.showusersettingsdialog
stdqtconstants.movietofileonlyexport
stdqtconstants.moviefilespecvalid,
exporter);
// need to explicitly quit (since awt is running)
system.exit(0);
} catch (qtexception qte) {
qte.printstacktrace();
}
}
public class exportchoice {
string name;
int subtype;
public exportchoice (string n, int st) {
name = n;
subtype = st;
}
public string tostring() {
return name;
}
}
}
package com.oreilly.qtjnotebook.ch04;
import quicktime.*;
import quicktime.io.*;
import quicktime.std.*;
import quicktime.std.comp.*;
import quicktime.std.image.*;
import quicktime.app.view.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.vector;
import java.io.*;
import com.oreilly.qtjnotebook.ch01.qtsessioncheck;
public class graphicimportexport extends object {
button exportbutton;
frame frame;
graphicsimporter importer;
static final int[] imagetypes =
{ stdqtconstants.kqtfiletypequicktimeimage};
/* other interesting values:
stdqtconstants.kqtfiletypegif,
stdqtconstants.kqtfiletypejpeg,
stdqtconstants4.kqtfiletypepng,
stdqtconstants4.kqtfiletypetiff
stdqtconstants.kqtfiletypemacpaint,
stdqtconstants.kqtfiletypephotoshop,
stdqtconstants.kqtfiletypepics,
stdqtconstants.kqtfiletypepicture,
*/
public static void main (string[] args) {
new graphicimportexport();
}
public graphicimportexport() {
try {
qtsessioncheck.check();
qtfile infile = qtfile.standardgetfilepreview (imagetypes);
importer = new graphicsimporter (infile);
// put image onscreen
qtcomponent qtc = qtfactory.makeqtcomponent (importer);
java.awt.component c = qtc.ascomponent();
frame = new frame ("imported image");
frame.setlayout (new borderlayout());
frame.add (c, borderlayout.center);
exportbutton = new button ("export");
exportbutton.addactionlistener (new actionlistener() {
public void actionperformed (actionevent ae) {
try {
doexport();
} catch (qtexception qte) {
qte.printstacktrace();
}
}
});
frame.add (exportbutton, borderlayout.south);
frame.pack();
frame.setvisible(true);
} catch (qtexception qte) {
qte.printstacktrace();
}
}
public void doexport() throws qtexception {
// build list of graphicexporters
vector choices = new vector();
componentdescription cd =
new componentdescription (
stdqtconstants.graphicsexportercomponenttype);
componentidentifier ci = null;
while ( (ci = componentidentifier.find(ci, cd)) != null) {
choices.add (new exportchoice (ci.getinfo().getname()
ci.getinfo().getsubtyp
}
// offer a choice of movie exporters
jcombobox exportcombo = new jcombobox (choices);
joptionpane.showmessagedialog (frame,
exportcombo,
"choose exporter",
joptionpane.plain_message);
exportchoice choice =
(exportchoice) exportcombo.getselecteditem();
system.out.println ("chose " + choice.name);
// build a ge, wire up to the graphicsimporter
graphicsexporter exporter =
new graphicsexporter (choice.subtype);
exporter.setinputgraphicsimporter (importer);
// ask for destination, settings
filedialog fd =
new filedialog (frame, "save as",
filedialog.save);
fd.setvisible(true);
string filename = fd.getfile();
if (filename.indexof('.') == -1)
filename = filename + "." +
exporter.getdefaultfilenameextension();
file file = new file (fd.getdirectory(), filename);
exporter.setoutputfile (new qtfile(file));
exporter.requestsettings();
// export
exporter.doexport();
// need to explicitly quit (since awt is running)
system.exit(0);
}
public class exportchoice {
string name;
int subtype;
public exportchoice (string n, int st) {
name = n;
subtype = st;
}
public string tostring() {
return name;
}
}
}
package com.oreilly.qtjnotebook.ch04;
import quicktime.*;
import quicktime.std.*;
import quicktime.std.comp.*;
import quicktime.util.qtutils;
import com.oreilly.qtjnotebook.ch01.qtsessioncheck;
public class componenttour {
public static void main (string[] args) {
try {
qtsessioncheck.check();
/* use this wildcard to show all components in qt
*/
componentdescription wildcard =
new componentdescription();
componentidentifier ci = null;
while ( (ci = componentidentifier.find(ci, wildcard)) != null) {
componentdescription cd = ci.getinfo();
system.out.println (cd.getname() +
" (" +
qtutils.fromostype (cd.gettype()) +
"/" +
qtutils.fromostype (cd.getsubtype()) +
} catch (qtexception qte) {
qte.printstacktrace();
}
}
}
run-ch04-componenttour:
[java] apple mp3 decoder (adec/.mp3) an audiocodec that decodes mpeg-1,
mpeg-2, mpeg-2.5 layer iii into linear pcm data
[java] mpeg-4 aac decoder (adec/aac ) an audiocodec that decodes mpeg-4
aac into linear pcm data
[java] apple lossless decoder (adec/alac) an audiocodec that decodes
apple lossless into linear pcm data
[java] apple ima4 decoder (adec/ima4) an audiocodec that decodes ima4
into linear pcm data
[java] mpeg-4 aac encoder (aenc/aac ) an audiocodec that encodes linear
pcm data into mpeg-4 aac
[java] apple lossless encoder (aenc/alac) an audiocodec that encodes
linear pcm data into apple lossless
[java] apple ima4 encoder (aenc/ima4) an audiocodec that encodes linear
pcm data into ima4
[java] applet (aplt/scpt) the component that runs script applications
[java] apple: auconverter (aufc/conv) audioconverter unit
[java] apple: auvarispeed (aufc/vari) apple's varispeed playback
[...]
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器