📄 jmfextending.html
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="GENERATOR" content="Quadralay WebWorks Publisher 5.0.2">
<meta name="TEMPLATEBASE" content="Portable HTML">
<meta name="LASTUPDATED" content="11/23/99 11:48:07">
<title>Extending JMF </title>
</head>
<body link="#3366CC" vlink="#9999CC" text="#000000" alink="#0000CC" bgcolor="#FFFFFF"
background="images/backgrnd.gif">
<table width="100%" border="0" align="left" cellpadding="0" cellspacing="0">
<tr>
<td><a href="JMFTOC.html">CONTENTS</a> |
<a href="JMFCapturing.html">PREV </a> |
<a href="Part2.html">NEXT</a> |
<a href="JMFIX.html">INDEX</a></td>
<td align="right"><em>JMF 2.0 API Guide</em>
</tr>
</table>
<p><br clear="all">
</p>
<hr align="left">
<blockquote>
<div align="right">
<a name="93825"> </a><font size="3" face="Palatino, Times New Roman, Times, serif">6 <br></font>
</div>
<div align="right">
<h2>
<a name="104351"> </a><font color="#003366" face="Palatino, Times New Roman, Times, serif">Extending JMF</font>
</h2>
</div>
<p>
<a name="101306"> </a><font face="Palatino, Times New Roman, Times, serif">You can extend JMF by implementing one of the plug-in interfaces to perform custom processing on a <code>Track</code>, or by implementing completely new <code>DataSources</code> and <code>MediaHandlers</code>.</font>
</p>
<p>
<a name="101320"> </a><font face="Palatino, Times New Roman, Times, serif">Note: <strong>JMF Players and Processors are not required to support plug-ins</strong>--plug-ins won't work with JMF 1.0-based Players and some 2.0-based implementations might choose not to support plug-ins. The reference implementation of JMF 2.0 provided by Sun Microsystems, Inc. and IBM Corporation fully supports the plug-in API. </font>
</p>
<h3>
<a name="101313"> </a><font color="#003366" face="Palatino, Times New Roman, Times, serif">Implementing JMF Plug-Ins</font>
</h3>
<p>
<a name="101337"> </a><font face="Palatino, Times New Roman, Times, serif">Custom JMF plug-ins can be used seamlessly with <code>Processors</code> that support the plug-in API. After you implement your plug-in, you need to install it and register it with the <code>PlugInManager</code> to make it available to plug-in compatible <code>Processors</code>.</font>
</p>
<h4>
<a name="101308"> </a><font color="#003366" face="Palatino, Times New Roman, Times, serif">Implementing a Demultiplexer Plug-In</font>
</h4>
<p>
<a name="94850"> </a><font face="Palatino, Times New Roman, Times, serif">A <code>Demultiplexer</code> parses media streams such as WAV, MPEG or QuickTime. If the stream is multiplexed, the separate tracks are extracted. You might want to implement a <code>Demultiplexer</code> plug-in to support a new file format or provide a higher-performance demultiplexer. If you implement a custom <code>DataSource</code>, you can implement a <code>Demultiplexer</code> plug-in that works with your custom <code>DataSource</code> to enable playback through an existing <code>Processor</code>.</font>
</p>
<p>
<a name="94851"> </a><font face="Palatino, Times New Roman, Times, serif">A <code>Demultiplexer</code> is a single-input, multi-output processing component. It reads data from a push or pull <code>DataSource</code>, extracts the individual tracks, and outputs each track separately. </font>
</p>
<p>
<a name="94852"> </a><font face="Palatino, Times New Roman, Times, serif">A <code>Demultiplexer</code> is a type of <code>MediaHandler</code>, it must implement the <code>MediaHandler</code> <code>setSource</code> method. This method is used by the <code>Processor</code> to locate a <code>Demultiplexer</code> that can handle its <code>DataSource</code>. The <code>Processor</code> goes through the list of registered <code>Demultiplexers</code> until it finds one that does not return an exception when <code>setSource</code> it called.</font>
</p>
<p>
<a name="95293"> </a><font face="Palatino, Times New Roman, Times, serif">The main work performed by a <code>Demultiplexer</code> is done in the implementation of the <code>getTracks</code> method, which returns an array of the tracks extracted from the input <code>DataSource</code>. </font>
</p>
<p>
<a name="95299"> </a><font face="Palatino, Times New Roman, Times, serif">A complete example of a GSM demultiplexer is provided in <a href="JMFApp-Demux.html#87606">Demultiplexer Plug-In</a>. When you implement a <code>Demultiplexer</code>, you need to:</font>
</p>
<ol type="1">
<li value="1"><a name="95300"> </a><font face="Palatino, Times New Roman, Times, serif">Implement <code>getSupportedInputContentDescriptors</code> to advertise what input formats the demulitplexer supports. For example, the GSM demultiplexer needs to advertise that it supports GSM files.</font>
</ol>
<a name="104575"> </a><font size="1" face="Palatino, Times New Roman, Times, serif">
<table border="1" bordercolorlight="#FFFFFF" bordercolordark="#000000"
cellpadding="5" cellspacing="0">
<caption><b><i><font face="Palatino, Times New Roman, Times, serif"><a name="104581"> </a>Example 6-1: Implementing getSupportedInputContentDescriptors.</font></i></b></caption>
<tr>
<td><font face="Palatino, Times New Roman, Times, serif"><pre>
<a name="104585"> </a><code> private static ContentDescriptor[] supportedFormat =
</code><a name="104586"> </a><code> new ContentDescriptor[] {new ContentDescriptor("audio.x_gsm")};
</code><a name="104587"> </a>
<a name="104588"> </a><code> public ContentDescriptor [] getSupportedInputContentDescriptors() {
</code><a name="104589"> </a><code> return supportedFormat;
</code><a name="104590"> </a><code> }
</code></pre>
</font></td>
</tr>
</table>
<br></font>
<ol type="1">
<li value="2"><a name="104616"> </a><font face="Palatino, Times New Roman, Times, serif">Implement the <code>MediaHandler</code> <code>setSource</code> method to check the <code>DataSource</code> and determine whether or not the <code>Demultiplexer</code> can handle that type of source. For example, the GSM demultiplexer supports <code>PullDataSources</code>:</font>
</ol>
<a name="104642"> </a><font size="1" face="Palatino, Times New Roman, Times, serif"><code>
<table border="1" bordercolorlight="#FFFFFF" bordercolordark="#000000"
cellpadding="5" cellspacing="0">
<caption><b><i><font face="Palatino, Times New Roman, Times, serif"><a name="104656"> </a>Example 6-2: Implementing setSource for a Demultiplexer. (1 of 2)</font></i></b></caption>
<tr>
<td><font face="Palatino, Times New Roman, Times, serif"><pre>
<a name="104736"> </a><code> public void setSource(DataSource source)
</code><a name="104737"> </a><code> throws IOException, IncompatibleSourceException {
</code><a name="104738"> </a>
<a name="104739"> </a><code> if (!(source instanceof PullDataSource)) {
</code><a name="104740"> </a><code> throw new IncompatibleSourceException("DataSource
not supported: " + source);
</code><a name="104741"> </a><code> } else {
</code><a name="104742"> </a><code> streams = ((PullDataSource) source).getStreams();
</code><a name="104743"> </a><code> }
</code></pre>
</font></td>
</tr>
<tr>
<td><font face="Palatino, Times New Roman, Times, serif"><pre>
<a name="104728"> </a><code> if ( streams == null) {
</code><a name="104729"> </a><code> throw new IOException("Got a null stream from the DataSource");
</code><a name="104730"> </a><code> }
</code><a name="104672"> </a>
<a name="104673"> </a><code> if (streams.length == 0) {
</code><a name="104674"> </a><code> throw new IOException("Got a empty stream array
from the DataSource");
</code><a name="104675"> </a><code> }
</code><a name="104676"> </a>
<a name="104677"> </a><code> this.source = source;
</code><a name="104678"> </a><code> this.streams = streams;
</code><a name="104679"> </a><code>
</code><a name="104680"> </a><code> positionable = (streams[0] instanceof Seekable);
</code><a name="104681"> </a><code> seekable = positionable && ((Seekable)
streams[0]).isRandomAccess();
</code><a name="104682"> </a>
<a name="104683"> </a><code> if (!supports(streams))
</code><a name="104684"> </a><code> throw new IncompatibleSourceException("DataSource not
supported: " + source);
</code><a name="104658"> </a><code> }
</code></pre>
</font></td>
</tr>
</table>
</code><br></font>
<ol type="1">
<li value="3"><a name="104758"> </a><font face="Palatino, Times New Roman, Times, serif">Implement <code>getTracks</code> to parse the header and extract the individual tracks from the stream if it is multiplexed. In the GSM demultiplexer a <code>readHeader</code> method is implemented to parse the header. The <code>getTracks</code> method returns an array of <code>GsmTracks</code>. (See <a href="JMFApp-Demux.html#87606">Demultiplexer Plug-In</a> for the implementation of <code>GsmTracks</code>.)</font>
</ol>
<a name="104793"> </a><font size="1" face="Palatino, Times New Roman, Times, serif"><code>
<table border="1" bordercolorlight="#FFFFFF" bordercolordark="#000000"
cellpadding="5" cellspacing="0">
<caption><b><i><font face="Palatino, Times New Roman, Times, serif"><a name="104806"> </a>Example 6-3: Implementing getTracks for a Demultiplexer. (1 of 2)</font></i></b></caption>
<tr>
<td><font face="Palatino, Times New Roman, Times, serif"><pre>
<a name="104855"> </a><code> public Track[] getTracks() throws IOException, BadHeaderException {
</code><a name="104856"> </a>
<a name="104857"> </a><code> if (tracks[0] != null)
</code><a name="104858"> </a><code> return tracks;
</code><a name="104859"> </a><code> stream = (PullSourceStream) streams[0];
</code><a name="104860"> </a><code> readHeader();
</code><a name="104861"> </a><code> bufferSize = bytesPerSecond;
</code><a name="104862"> </a><code> tracks[0] = new GsmTrack((AudioFormat) format,
</code><a name="104863"> </a><code> /*enabled=*/ true,
</code><a name="104864"> </a><code> new Time(0),
</code><a name="104865"> </a><code> numBuffers,
</code><a name="104866"> </a><code> bufferSize,
</code><a name="104867"> </a><code> minLocation,
</code><a name="104868"> </a><code> maxLocation
</code><a name="104869"> </a><code> );
</code><a name="104870"> </a><code> return tracks;
</code><a name="104871"> </a><code> }
</code></pre>
</font></td>
</tr>
<tr>
<td><font face="Palatino, Times New Roman, Times, serif"><pre>
<a name="104827"> </a><code>// ...
</code><a name="104828"> </a>
<a name="104829"> </a><code> private void readHeader()
</code><a name="104830"> </a><code> throws IOException, BadHeaderException {
</code><a name="104831"> </a>
<a name="104832"> </a><code> minLocation = getLocation(stream); // Should be zero
</code><a name="104833"> </a>
<a name="104834"> </a><code> long contentLength = stream.getContentLength();
</code><a name="104835"> </a><code> if ( contentLength != SourceStream.LENGTH_UNKNOWN ) {
</code><a name="104836"> </a><code> double durationSeconds = contentLength / bytesPerSecond;
</code><a name="104837"> </a><code> duration = new Time(durationSeconds);
</code><a name="104838"> </a><code> maxLocation = contentLength;
</code><a name="104839"> </a><code> } else {
</code><a name="104840"> </a><code> maxLocation = Long.MAX_VALUE;
</code><a name="104808"> </a><code> }
</code></pre>
</font></td>
</tr>
</table>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -