/* * JMFMerger.java * * Version 1.0 Sep 18, 2008 * * Copyright notice * * Brief description * * (c) 2008 by dbreuer */ package de.fhkoeln.santiago.components.jmf; import java.io.IOException; import java.util.Vector; import javax.media.ControllerEvent; import javax.media.ControllerListener; import javax.media.DataSink; import javax.media.EndOfMediaEvent; import javax.media.Format; import javax.media.Manager; import javax.media.MediaException; import javax.media.MediaLocator; import javax.media.Processor; import javax.media.ProcessorModel; import javax.media.datasink.DataSinkErrorEvent; import javax.media.datasink.DataSinkEvent; import javax.media.datasink.DataSinkListener; import javax.media.datasink.EndOfStreamEvent; import javax.media.format.AudioFormat; import javax.media.format.VideoFormat; import javax.media.protocol.ContentDescriptor; import javax.media.protocol.DataSource; import javax.media.protocol.FileTypeDescriptor; public class JMFMerger implements ControllerListener, DataSinkListener, MediaAction { private final Vector sourceURIs = new Vector(1); private final String outputPath; private String videoEncoding = "JPEG"; private String audioEncoding = "LINEAR"; private String outputType = FileTypeDescriptor.QUICKTIME; private DataSource merger; private DataSource outputDataSource; private DataSource[] dataOutputs; private DataSink outputDataSink; private Processor outputProcessor; private Processor[] processors; private ProcessorModel outputModel; private MediaLocator outputLocator; private VideoFormat videoFormat; private AudioFormat audioFormat; private boolean done = false; public JMFMerger(String pathToMovie, String pathToAudio, String outputPath) { this.outputPath = outputPath; sourceURIs.add(pathToMovie); sourceURIs.add(pathToAudio); } public void controllerUpdate(ControllerEvent event) { if (event instanceof EndOfMediaEvent) { synchronized (this) { outputProcessor.close(); outputProcessor = null; } } } public void dataSinkUpdate(DataSinkEvent event) { if (event instanceof EndOfStreamEvent) { done = true; } else if (event instanceof DataSinkErrorEvent) { done = true; } } public void performAction() { try { processors = new Processor[sourceURIs.size()]; dataOutputs = new DataSource[sourceURIs.size()]; for (int i = 0; i < sourceURIs.size(); i++) { String sourceURI = (String) sourceURIs.get(i); MediaLocator locator = new MediaLocator(sourceURI); ProcessorModel processorModel = new MergeProcessorModel(locator); processors[i] = Manager.createRealizedProcessor(processorModel); dataOutputs[i] = processors[i].getDataOutput(); processors[i].start(); } merger = Manager.createMergingDataSource(dataOutputs); merger.connect(); merger.start(); if (merger == null) throw new MediaException("Failed to merge data sources."); ProcessorModel outputProcessorModel = new OutputProcessorModel(merger); outputProcessor = Manager.createRealizedProcessor(outputProcessorModel); outputDataSource = outputProcessor.getDataOutput(); outputLocator = new MediaLocator(outputPath); outputDataSink = Manager.createDataSink(outputDataSource, outputLocator); outputDataSink.open(); outputProcessor.addControllerListener(this); outputDataSink.addDataSinkListener(this); System.out.println("Merging..."); outputDataSink.start(); outputProcessor.start(); int count = 0; while (!done) { try { Thread.currentThread().sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } if (outputProcessor != null && (int) (outputProcessor.getMediaTime().getSeconds()) > count) { System.out.print("."); count = (int) (outputProcessor.getMediaTime().getSeconds()); } } if (outputDataSink != null) { outputDataSink.close(); } synchronized (this) { if (outputProcessor != null) { outputProcessor.close(); } } System.out.println("Added Audio to Movie file!"); } catch (MediaException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } class MergeProcessorModel extends ProcessorModel { private MediaLocator inputLocator; public MergeProcessorModel(MediaLocator locator) { this.inputLocator = locator; } public ContentDescriptor getContentDescriptor() { return new ContentDescriptor(ContentDescriptor.RAW); } public DataSource getInputDataSource() { return null; } public MediaLocator getInputLocator() { return inputLocator; } public Format getOutputTrackFormat(int index) { return null; } public int getTrackCount(int n) { return n; } public boolean isFormatAcceptable(int index, Format format) { if (videoFormat == null) { videoFormat = new VideoFormat(videoEncoding); } if (audioFormat == null) { audioFormat = new AudioFormat(audioEncoding); } if (format.matches(videoFormat) || format.matches(audioFormat)) return true; else return false; } } class OutputProcessorModel extends ProcessorModel { private final DataSource inputDataSource; public OutputProcessorModel(DataSource inputDataSource) { this.inputDataSource = merger; } public ContentDescriptor getContentDescriptor() { return new FileTypeDescriptor(outputType); } public DataSource getInputDataSource() { return inputDataSource; } public MediaLocator getInputLocator() { return null; } public Format getOutputTrackFormat(int index) { return null; } public int getTrackCount(int n) { return n; } public boolean isFormatAcceptable(int index, Format format) { if (videoFormat == null) { videoFormat = new VideoFormat(videoEncoding); } if (audioFormat == null) { audioFormat = new AudioFormat(audioEncoding); } if (format.matches(videoFormat) || format.matches(audioFormat)) return true; else return false; } } }