/** Gets an image via the cam */ boolean camFetchFrame() { try { if (converter == null) { pbs.read(buffer); } else { if (inputBuffer == null) { inputBuffer = new Buffer(); } pbs.read(inputBuffer); converter.process(inputBuffer, buffer); } if (buffer.isDiscard()) { buffer.setDiscard(false); return false; } if (buffer.getData() == null) { return false; } } catch (Exception e) { return false; } return true; }
/** Write the buffer to the SourceDataLine. */ public int process(Buffer buffer) { // if we need to convert the format, do so using the codec. if (codec != null) { final int codecResult = codec.process(buffer, codecBuffer); if (codecResult == BUFFER_PROCESSED_FAILED) return BUFFER_PROCESSED_FAILED; if (codecResult == OUTPUT_BUFFER_NOT_FILLED) return BUFFER_PROCESSED_OK; buffer = codecBuffer; } int length = buffer.getLength(); int offset = buffer.getOffset(); final Format format = buffer.getFormat(); final Class type = format.getDataType(); if (type != Format.byteArray) { return BUFFER_PROCESSED_FAILED; } final byte[] data = (byte[]) buffer.getData(); final boolean bufferNotConsumed; final int newBufferLength; // only applicable if bufferNotConsumed final int newBufferOffset; // only applicable if bufferNotConsumed if (NON_BLOCKING) { // TODO: handle sourceLine.available(). This code currently causes choppy audio. if (length > sourceLine.available()) { // we should only write sourceLine.available() bytes, then return INPUT_BUFFER_NOT_CONSUMED. length = sourceLine.available(); // don't try to write more than available bufferNotConsumed = true; newBufferLength = buffer.getLength() - length; newBufferOffset = buffer.getOffset() + length; } else { bufferNotConsumed = false; newBufferLength = length; newBufferOffset = offset; } } else { bufferNotConsumed = false; newBufferLength = 0; newBufferOffset = 0; } if (length == 0) { logger.finer("Buffer has zero length, flags = " + buffer.getFlags()); } // make sure all the bytes are written. while (length > 0) { // logger.fine("Available: " + sourceLine.available()); // logger.fine("length: " + length); // logger.fine("sourceLine.getBufferSize(): " + sourceLine.getBufferSize()); final int n = sourceLine.write( data, offset, length); // TODO: this can block for a very long time if it doesn't if (n >= length) break; else if (n == 0) { // TODO: we could choose to handle a write failure this way, // assuming that it is considered legal to call stop while process is being called. // however, that seems like a bad idea in general. // if (!sourceLine.isRunning()) // { // buffer.setLength(offset); // buffer.setOffset(length); // return INPUT_BUFFER_NOT_CONSUMED; // our write was interrupted. // } logger.warning( "sourceLine.write returned 0, offset=" + offset + "; length=" + length + "; available=" + sourceLine.available() + "; frame size in bytes" + sourceLine.getFormat().getFrameSize() + "; sourceLine.isActive() = " + sourceLine.isActive() + "; " + sourceLine.isOpen() + "; sourceLine.isRunning()=" + sourceLine.isRunning()); return BUFFER_PROCESSED_FAILED; // sourceLine.write docs indicate that this will only happen // if there is an error. } else { offset += n; length -= n; } } if (bufferNotConsumed) { // return INPUT_BUFFER_NOT_CONSUMED if not all bytes were written buffer.setLength(newBufferLength); buffer.setOffset(newBufferOffset); return INPUT_BUFFER_NOT_CONSUMED; } if (buffer.isEOM()) { // TODO: the proper way to do this is to implement Drainable, and let the processor call our // drain method. sourceLine .drain(); // we need to ensure that the media finishes playing, otherwise the EOM event // will // be posted before the media finishes playing. } return BUFFER_PROCESSED_OK; }