FileDocCategorySizeDatePackage
BasicPullParser.javaAPI DocJMF 2.1.1e11308Mon May 12 12:20:52 BST 2003com.sun.media.parser

BasicPullParser

public abstract class BasicPullParser extends BasicPlugIn implements Demultiplexer

Fields Summary
protected DataSource
source
protected SourceStream[]
streams
private Format[]
outputFormats
private byte[]
b
private byte[]
intArray
private byte[]
shortArray
private final int
TEMP_BUFFER_LENGTH
private byte[]
tempBuffer
private long
currentLocation
protected boolean
seekable
protected boolean
positionable
protected CachedStream
cacheStream
private Object
sync
Constructors Summary
Methods Summary
public voidclose()
Closes the plug-in component and releases resources. No more data will be accepted by the plug-in after a call to this method. The plug-in can be reinstated after being closed by calling open.

	if (source != null) {
	    try {
		source.stop();
		source.disconnect();
	    } catch (IOException e) {
		// Internal error?
	    }
	    source = null;
	}
    
public final longgetLocation(javax.media.protocol.PullSourceStream pss)

	synchronized(sync) {
	    if ( (pss instanceof Seekable) )
		return ((Seekable)pss).tell();
	    else
		return currentLocation;
	}
    
public abstract javax.media.protocol.ContentDescriptor[]getSupportedInputContentDescriptors()
Lists the possible input formats supported by this plug-in.

public booleanisPositionable()

	return positionable;
    
public booleanisRandomAccess()

	return seekable;
    
public voidopen()
Opens the plug-in software or hardware component and acquires necessary resources. If all the needed resources could not be acquired, it throws a ResourceUnavailableException. Data should not be passed into the plug-in without first calling this method.

	// throws ResourceUnavailableException;
    
protected intparseIntFromArray(byte[] array, int offset, boolean isBigEndian)

	int result;

	if (isBigEndian) {
	    result = ((array[offset+0] & 0xFF) << 24) | 
		     ((array[offset+1] & 0xFF) << 16) | 
		     ((array[offset+2] & 0xFF) << 8) |
		     (array[offset+3] & 0xFF);
	} else {
	    result = ((array[offset+3] & 0xFF) << 24) |
		     ((array[offset+2] & 0xFF) << 16) |
		     ((array[offset+1] & 0xFF) << 8) |
		     (array[offset+0] & 0xFF);
	}
	return result;
    
public static final shortparseShortFromArray(byte[] array, boolean isBigEndian)

	if (array.length < 2)
	    throw new IOException("Unexpected EOF");

	int result;

	if (isBigEndian) {
	    result = ((array[0] &0xFF) << 8) |
		     (array[1] &0xFF);
	} else {
	    result = ((array[1] &0xFF) << 8) |
		     (array[0] & 0xFF);
	}
	return (short) result;

    
public intreadByte(javax.media.protocol.PullSourceStream pss)

	readBytes(pss, b, 1);
	return (int) b[0];
    
public intreadBytes(javax.media.protocol.PullSourceStream pss, byte[] array, int numBytes)
Read numBytes from offset 0


	return readBytes(pss, array, 0, numBytes);
    
public intreadBytes(javax.media.protocol.PullSourceStream pss, byte[] array, int offset, int numBytes)

	//TODO	synchronized(array) {

	// Is this if check too much overhead?
	// Can we rely on parsers to call this method with valid args?
	if (array == null) {
	    throw new NullPointerException();
	} else if ((offset < 0) || (offset > array.length) || (numBytes < 0) ||
		   ((offset + numBytes) > array.length) || ((offset + numBytes) < 0)) {
	    throw new IndexOutOfBoundsException();
	} else if (numBytes == 0) {
	    return 0;
	}

	int remainingLength = numBytes;
	int actualRead = 0;

	remainingLength = numBytes;
	while (remainingLength > 0) {

		actualRead = pss.read(array, offset, remainingLength);
		if (actualRead == -1) {// End of stream
		    if (offset == 0) {
			// Note: Using this as we don't have EndOfMediaException
			throw new IOException("BasicPullParser: readBytes(): Reached end of stream while trying to read " + numBytes + " bytes");
		    } else {
			// System.out.println("readBytes: ASKED for " + numBytes +
			// " GOT " + offset +
			// "NEXT read will be EOM");
			return offset;
		    }
		} else if (actualRead == com.sun.media.protocol.BasicSourceStream.LENGTH_DISCARD) {
		    return com.sun.media.protocol.BasicSourceStream.LENGTH_DISCARD;
		} else if (actualRead < 0) {
		    throw new IOException("BasicPullParser: readBytes() read returned " + actualRead);
		}
		remainingLength -= actualRead;
		// System.out.println("  remainingLength is " + remainingLength);
		offset += actualRead;
		synchronized(sync) {
		    currentLocation += actualRead;
		}
	}
	return numBytes;
	// System.out.println("Finished reading " + numBytes);
	//TODO	}
    
protected intreadInt(javax.media.protocol.PullSourceStream pss, boolean isBigEndian)

	int result;

	readBytes(pss, intArray, 4);
	if (isBigEndian) {
	    result = ((intArray[0] & 0xFF) << 24) | 
		     ((intArray[1] & 0xFF) << 16) | 
		     ((intArray[2] & 0xFF) << 8) |
		     (intArray[3] & 0xFF);
	} else {
	    result = ((intArray[3] & 0xFF) << 24) |
		     ((intArray[2] & 0xFF) << 16) |
		     ((intArray[1] & 0xFF) << 8) |
		     (intArray[0] & 0xFF);
	}
	return result;
    
public intreadInt(javax.media.protocol.PullSourceStream pss)

	return readInt(pss, true);
    
protected shortreadShort(javax.media.protocol.PullSourceStream pss, boolean isBigEndian)

	int result;

	readBytes(pss, shortArray, 2);
	if (isBigEndian) {
	    result = ((shortArray[0] &0xFF) << 8) |
		     (shortArray[1] &0xFF);
	} else {
	    result = ((shortArray[1] &0xFF) << 8) |
		     (shortArray[0] & 0xFF);
	}
	return (short) result;
    
public intreadShort(javax.media.protocol.PullSourceStream pss)

	return readShort(pss, true);
    
protected java.lang.StringreadString(javax.media.protocol.PullSourceStream pss)

	readBytes(pss, intArray, 4);
	return new String(intArray);
    
public voidreset()
Resets the state of the plug-in. Typically at end of media or when media is repositioned.

    
public voidsetSource(javax.media.protocol.DataSource source)

 // synchronizing variable


       
	   

	if (!(source instanceof PullDataSource)) {
	    throw new IncompatibleSourceException("DataSource not supported: " + source);
	} else {
	    streams = ((PullDataSource) source).getStreams();
	}


	if ( streams == null) {
	    throw new IOException("Got a null stream from the DataSource");
	}

	if (streams.length == 0) {
	    throw new IOException("Got a empty stream array from the DataSource");
	}

	this.source = source;
	this.streams = streams;
	
	positionable =  (streams[0] instanceof Seekable);
	seekable =  positionable && ((Seekable) streams[0]).isRandomAccess();

	if (!supports(streams))
	    throw new IncompatibleSourceException("DataSource not supported: " + source);

	try {
	    cacheStream = (CachedStream) streams[0];
	} catch (ClassCastException e) {
	    // System.out.println("bpparser: cacheStream is null");
	    cacheStream = null;
	}
    
public voidskip(javax.media.protocol.PullSourceStream pss, int numBytes)


	// System.out.println("skip : " + numBytes);
	// System.out.println("seekable is " + (pss instanceof Seekable));
	if ( (pss instanceof Seekable) && ((Seekable)pss).isRandomAccess() ) {
	    long current = ((Seekable)pss).tell();
	    long newPos = current + numBytes;
	    // System.out.println("bpp:skip " + numBytes + " : " + current + " : " + newPos);
	    ((Seekable)pss).seek( newPos );
	    if (newPos != ((Seekable)pss).tell()) {
		// System.out.println("DEBUG: seek to " + newPos + " failed");
		// Is this the correct thing to do?
		throw new IOException("Seek to " + newPos + " failed");
	    }
            synchronized(sync) {
                currentLocation += numBytes;
            }
	    return;
	}
	// NOTE: readBytes with null as second arg. should do the job.
	// But there is a bug in the PullSourceStream implementation
	// readBytes(pss, null, numBytes);

	int remaining = numBytes;
	int bytesRead;
	while (remaining > TEMP_BUFFER_LENGTH) {
	    // System.out.println("Calling readBytes " + TEMP_BUFFER_LENGTH);
	    bytesRead = readBytes(pss, tempBuffer, TEMP_BUFFER_LENGTH);
	    if (bytesRead != TEMP_BUFFER_LENGTH) {
		throw new IOException("BasicPullParser: End of Media reached while trying to skip " + numBytes);
	    }
	    remaining -= TEMP_BUFFER_LENGTH;
	}
	if (remaining > 0) {
	    // System.out.println("Calling readBytes " + remaining);
	    bytesRead = readBytes(pss, tempBuffer, remaining);
	    if (bytesRead != remaining) {
		throw new IOException("BasicPullParser: End of Media reached while trying to skip " + numBytes);
	    }
	}
	synchronized(sync) {
	    currentLocation += numBytes;
	}
    
public voidstart()
This get called when the player/processor is started.

 	if (source != null)
 	    source.start();
    
public voidstop()
This get called when the player/processor is stopped.

	if (source != null) {
	    try {
		source.stop();
	    } catch (IOException e) {
		// Internal errors?
	    }
	}
    
protected booleansupports(javax.media.protocol.SourceStream[] streams)
A parser may support pull only or push only or both pull and push streams. Some parsers may have other requirements. A quicktime parser imposes an additional requirement that isSeekable() and isRandomAccess() be true Override this if the Parser has additional requirements from the PullSourceStream

	return ( (streams[0] != null) &&
		 (streams[0] instanceof PullSourceStream) );