private InputStream getInputStream( String urlStr, Format outputFormat, ContentDescriptor outputContentDescriptor) throws Exception { final ProcessorModel processorModel = new ProcessorModel( new MediaLocator(urlStr), outputFormat == null ? null : new Format[] {outputFormat}, outputContentDescriptor); final Processor processor = Manager.createRealizedProcessor(processorModel); final DataSource ds = processor.getDataOutput(); final DataSink[] streamDataSinkHolder = new DataSink[] {null}; // connect the data output of the processor to a StreamDataSink, which // will make the data available to PipedInputStream, which we return. final PipedInputStream in = new PipedInputStream() { // override close to clean up everything when the media has been // served. @Override public void close() throws IOException { super.close(); logger.fine("Closed input stream"); logger.fine("Stopping processor"); processor.stop(); logger.fine("Closing processor"); processor.close(); logger.fine("Deallocating processor"); processor.deallocate(); if (streamDataSinkHolder[0] != null) { logger.fine("Closing StreamDataSink"); streamDataSinkHolder[0].close(); } } }; final PipedOutputStream out = new PipedOutputStream(in); final DataSink streamDataSink = new StreamDataSink(out); streamDataSinkHolder[0] = streamDataSink; streamDataSink.setSource(ds); streamDataSink.open(); streamDataSink.start(); logger.info("Starting processor"); processor.start(); // TODO: if there is an error, make sure we clean up. // for example, if the client breaks the connection. // we need a controller listener to listen for errors. return in; }