Author: michiel
Date: 2009-07-02 14:52:01 +0200 (Thu, 02 Jul 2009)
New Revision: 36518

Added:
   
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/MimeType.java
   
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/Recognizer.java
   
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/RecognizerTranscoder.java
Modified:
   
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/CreateCachesProcessor.java
   
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/AbstractTranscoder.java
   
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/CommandTranscoder.java
   
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/FFMpeg2TheoraTranscoder.java
   
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/FFMpegTranscoder.java
   
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/InfiniteTranscoder.java
   
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/Transcoder.java
   
mmbase/trunk/applications/streams/src/main/resources/org/mmbase/streams/resources/createcaches.xsd
   
mmbase/trunk/applications/streams/src/main/webapp/mmbase/components/streams/admin.jspx
   
mmbase/trunk/applications/streams/src/main/webapp/mmbase/components/streams/alljobs.jspx
Log:
moved code around a bit to allow for 'in' attributes on transcoders, by which 
you can define the input of one transcoder to be the output of another one

Modified: 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/CreateCachesProcessor.java
===================================================================
--- 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/CreateCachesProcessor.java
       2009-07-02 10:50:24 UTC (rev 36517)
+++ 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/CreateCachesProcessor.java
       2009-07-02 12:52:01 UTC (rev 36518)
@@ -22,6 +22,7 @@
 import org.mmbase.util.externalprocess.CommandExecutor;
 import org.mmbase.datatypes.processors.*;
 import org.mmbase.applications.media.State;
+import org.mmbase.applications.media.Format;
 import org.mmbase.servlet.FileServlet;
 import org.mmbase.core.event.*;
 
@@ -36,7 +37,7 @@
 
 /**
  * This commit-processor is used on nodes of type 'streamsources' and is used 
to initiate the
- * conversions to other formats which are saved in 'streamsourcescaches'. Its 
analogy is derived 
+ * conversions to other formats which are saved in 'streamsourcescaches'. Its 
analogy is derived
  * from the conversion of 'images' in MMBase to their resulting 'icaches' 
nodes.
  *
  * @author Michiel Meeuwissen
@@ -55,7 +56,7 @@
         EntityResolver.registerSystemID(NAMESPACE_CREATECACHES + ".xsd", 
XSD_CREATECACHES, CreateCachesProcessor.class);
     }
 
-    private static List<JobDefinition> list = new 
CopyOnWriteArrayList<JobDefinition>();
+    private static Map<String, JobDefinition> list = 
Collections.synchronizedMap(new LinkedHashMap<String, JobDefinition>());
 
     private static int transSeq = 0;
     public final ThreadPoolExecutor transcoderExecutor = new 
ThreadPoolExecutor(3, 3, 5 * 60 , TimeUnit.SECONDS, new 
LinkedBlockingQueue<Runnable>(), new ThreadFactory() {
@@ -80,7 +81,7 @@
             public void onChange(String resource) {
                 try {
                     LOG.service("Reading " + resource);
-                    List<JobDefinition> newList = new 
ArrayList<JobDefinition>();
+                    Map<String, JobDefinition> newList = new 
LinkedHashMap<String, JobDefinition>();
                     List<CommandExecutor.Method> newExecutors = new 
ArrayList<CommandExecutor.Method>();
                     Document document = 
getResourceLoader().getDocument(resource);
                     if (document != null) {
@@ -91,7 +92,12 @@
                             if (ellist.item(i) instanceof Element) {
                                 Element el = (Element) ellist.item(i);
                                 if (el.getTagName().equals("transcoder")) {
-                                    Transcoder transcoder = (Transcoder) 
Instantiator.getInstanceWithSubElement(el);
+                                    String id = el.getAttribute("id");
+                                    Transcoder transcoder = (Transcoder) 
Instantiator.getInstanceWithSubElement(el, id);
+                                    String in = el.getAttribute("in");
+                                    if (in.length() > 0) {
+                                        transcoder.setInId(in);
+                                    }
                                     LOG.debug("Created " + transcoder);
                                     JobDefinition def = new 
JobDefinition(transcoder);
                                     org.w3c.dom.NodeList childs = 
el.getChildNodes();
@@ -105,7 +111,7 @@
                                             }
                                         }
                                     }
-                                    newList.add(def);
+                                    newList.put(id, def);
                                 } else if 
(el.getTagName().equals("localhost")) {
                                     int max = 
Integer.parseInt(el.getAttribute("max_simultaneous_transcoders"));
                                     totalTranscoders += max;
@@ -130,7 +136,7 @@
                         LOG.warn("No " + resource);
                     }
                     list.clear();
-                    list.addAll(newList);
+                    list.putAll(newList);
                     synchronized(executors) {
                         executors.clear();
                         executors.addAll(newExecutors);
@@ -160,73 +166,9 @@
         initWatcher();
     }
 
-    /**
-     * Gets the node representing the 'cached' stream (the result of a 
conversion).
-     * @param cacheManager
-     * @param node  the original node from which the 'cached' stream was 
created
-     * @param key   representation of the way the stream was created from its 
source 
-     * @param logger
-     */
-    protected Node getCacheNode(final String cacheManager, final Node node, 
final String key,  final Logger logger) {
-        final NodeManager caches = 
node.getCloud().getNodeManager(cacheManager);
-        NodeQuery q = caches.createQuery();
-        Queries.addConstraint(q, Queries.createConstraint(q, "id",  
FieldCompareConstraint.EQUAL, node));
-        Queries.addConstraint(q, Queries.createConstraint(q, "key", 
FieldCompareConstraint.EQUAL, key));
 
-        LOG.service("Executing " + q.toSql());
-        NodeList nodes = caches.getList(q);
-        if (nodes.size() > 0) {
-            return nodes.getNode(0);
-        }
-        return null;
-    }
 
-    /**
-     * Gets, and if necessary creates, the node representing the 'cached' 
stream (the result of a
-     * conversion).
-     * @param node The original node
-     * @param mediaprovider
-     * @param mediafragment
-     * @param transcoder The transcoder providing the 'key'.
-     */
-    protected Node getCacheNode(final Node node, final Node mediaprovider, 
final Node mediafragment, final Transcoder t, final Logger logger) {
-        assert mediafragment != null;
-        assert mediaprovider != null;
 
-        final String key = t.getKey();
-        Node resultNode = null;
-        for (String cacheType : new String[] {"streamsourcescaches", 
"videostreamsourcescaches", "audiostreamsourcescaches"}) {
-            resultNode = getCacheNode(cacheType, node, key, logger);
-            if (resultNode != null) break;
-        }
-
-        final NodeManager caches = 
node.getCloud().getNodeManager(node.getNodeManager().getProperty("org.mmbase.streams.cachestype"));
-
-        if (resultNode != null) {
-            resultNode.setIntValue("state",  State.REQUEST.getValue());
-            resultNode.commit();
-        } else {
-            resultNode = caches.createNode();
-            resultNode.setIntValue("state",  State.REQUEST.getValue());
-            resultNode.setStringValue("key", t.getKey());
-            resultNode.setIntValue("format", t.getFormat().toInt());
-            resultNode.setIntValue("codec", t.getCodec().toInt());
-            resultNode.setNodeValue("id",    node);
-            resultNode.commit();
-
-            // virtual field actually creates relation
-            resultNode.setNodeValue("mediaprovider", mediaprovider);
-            resultNode.setNodeValue("mediafragment", mediafragment);
-            resultNode.commit();
-            logger.info("Created cache node " + resultNode.getNumber()  + " 
for provider " + mediaprovider.getNumber() + " fragment " + 
mediafragment.getNumber());
-
-        }
-        return resultNode;
-    }
-
-
-
-
     private static final Map<Integer, Job> runningJobs = 
Collections.synchronizedMap(new LinkedHashMap<Integer, Job>());
 
 
@@ -270,93 +212,50 @@
         }
     }
 
-    public List<JobDefinition> getConfiguration() {
-        return Collections.unmodifiableList(list);
+    public Map<String, JobDefinition> getConfiguration() {
+        return Collections.unmodifiableMap(list);
     }
 
 
-    private Job createJob(final Node node, final Node mediaprovider, final 
Node mediafragment, final ChainedLogger logger) {
+    private Job createJob(final Node node, final ChainedLogger logger) {
         Job job = runningJobs.get(node.getNumber());
         if (job != null) {
             // already running
             return null;
         }
-        final Job thisJob = new Job(node, logger, list.size());
+        final Job thisJob = new Job(node, logger, list);
+        runningJobs.put(node.getNumber(), thisJob);
 
-        runningJobs.put(node.getNumber(), thisJob);
         thisJob.setFuture(transcoderExecutor.submit(new Callable<Integer>() {
                     public Integer call() {
                         thisJob.setThread(Thread.currentThread());
                         int result = 0;
                         try {
-                            final List<JobDefinition> clones = new 
ArrayList<JobDefinition>();
-                            try {
-                                for (JobDefinition jd : list) {
-                                    JobDefinition clone = new 
JobDefinition(jd);
-                                    clones.add(clone);
-                                    getCacheNode(node, mediaprovider, 
mediafragment, clone.transcoder, logger);
-                                }
-                            } catch (Exception e) {
-                                logger.error(e.getClass() + " " + 
e.getMessage(), e);
-                            }
-                            LOG.info("Using " + clones);
-                            for (final JobDefinition jd : clones) {
+                            LOG.info("Using " + thisJob.clones);
+                            for (final JobDefinition jd : thisJob) {
                                 logger.service("NOW doing " + jd);
-                                thisJob.setTranscoder(jd.transcoder);
-                                Node cacheNode = 
CreateCachesProcessor.this.getCacheNode(node, mediaprovider, mediafragment, 
jd.transcoder, logger);
-                                File inFile = new 
File(FileServlet.getDirectory(), node.getStringValue("url"));
-                                URI in = inFile.toURI();
-                                StringBuilder buf = new StringBuilder();
-                                
org.mmbase.storage.implementation.database.DatabaseStorageManager.appendDirectory(buf,
 cacheNode.getNumber(), "/");
-                                buf.append(cacheNode.getNumber()).append(".");
-                                
buf.append(ResourceLoader.getName(inFile.getName())).append(".").append(jd.transcoder.getFormat().toString().toLowerCase());
-                                File outFile = new 
File(FileServlet.getDirectory(), buf.toString().replace("/", File.separator));
-                                logger.service("Transcoding with " + 
jd.transcoder + " for " + in + " -> " + outFile);
+                                URI in = jd.getIn();
+                                URI out = jd.getOut();
+
                                 final List<AnalyzerLogger> analyzerLoggers = 
new ArrayList<AnalyzerLogger>();
                                 for (Analyzer a: jd.analyzers) {
-                                    AnalyzerLogger al = new 
AnalyzerLogger(a.clone(), node, cacheNode);
+                                    AnalyzerLogger al = new 
AnalyzerLogger(a.clone(), thisJob.getNode(), jd.getResultNode());
                                     analyzerLoggers.add(al);
                                     logger.addLogger(al);
                                 }
                                 try {
-                                    cacheNode.setIntValue("state", 
State.BUSY.getValue());
-                                    cacheNode.setStringValue("url", 
buf.toString());
-                                    cacheNode.commit();
-                                    if (jd.transcoder instanceof 
CommandTranscoder) {
-                                        // Get free method
-                                        CommandExecutor.Method m = null;
-                                        synchronized(executors) {
-                                            for (CommandExecutor.Method e : 
executors) {
-                                                if (! e.isInUse()) {
-                                                    e.setInUse(true);
-                                                    m = e;
-                                                    break;
-                                                }
-                                            }
-                                        }
-                                        if (m == null) {
-                                            LOG.error("There should always be 
a free CommandExecutor. Using LAUCHER now.");
-                                        } else {
-                                            ((CommandTranscoder) 
jd.transcoder).setMethod(m);
-                                        }
-                                    }
-
-                                    jd.transcoder.transcode(in, 
outFile.toURI(), logger);
+                                    jd.transcoder.transcode(in, out, logger);
                                     for (AnalyzerLogger al : analyzerLoggers) {
-                                        al.getAnalyzer().ready(node, 
cacheNode);
+                                        
al.getAnalyzer().ready(thisJob.getNode(), jd.getResultNode());
                                     }
-                                    if (node.isChanged()) {
-                                        node.commit();
-                                    }
-                                    cacheNode.setLongValue("filesize", 
outFile.length());
-                                    cacheNode.setIntValue("state",
-                                                          
State.DONE.getValue());
-                                    cacheNode.commit();
                                     result++;
                                     logger.info("READY " + thisJob);
                                     if (thisJob.isInterrupted() || 
Thread.currentThread().isInterrupted()){
-                                        cacheNode.setIntValue("state", 
State.INTERRUPTED.getValue());
-                                        cacheNode.commit();
+                                        Node cacheNode = jd.getResultNode();
+                                        if (cacheNode != null) {
+                                            cacheNode.setIntValue("state", 
State.INTERRUPTED.getValue());
+                                            cacheNode.commit();
+                                        }
                                         logger.info("Interrupted");
                                         break;
                                     }
@@ -381,7 +280,7 @@
                             throw e;
                         } finally {
                             logger.info("READY " + result);
-                            runningJobs.remove(thisJob.getNodeNumber());
+                            runningJobs.remove(thisJob.getNode().getNumber());
                         }
                         return result;
 
@@ -398,15 +297,9 @@
             final ChainedLogger logger = new ChainedLogger(LOG);
             final Node ntNode = ntCloud.getNode(node.getNumber());
             ntNode.getStringValue("title"); // This triggers 
RelatedField$Creator to create a
-            // mediafragment if it does not yet exist
-            final Node mediafragment = 
ntCloud.getNode(ntNode.getNodeValue("mediafragment").getNumber());
-            final Node mediaprovider = 
ntCloud.getNode(ntNode.getNodeValue("mediaprovider").getNumber());
+            LOG.info("Triggering caches for " + list + " Mediaframent " + 
node.getNodeValue("mediafragment").getNumber());
 
-            LOG.info("Triggering caches for " + list + " Mediaframent " + 
mediafragment);
-
-            final Job thisJob = createJob(ntNode,
-                                          mediaprovider,
-                                          mediafragment, logger);
+            final Job thisJob = createJob(ntNode, logger);
             if (thisJob != null) {
 
                 // If the node happens to be deleted before the future with 
cache creations is ready, cancel the future
@@ -458,19 +351,28 @@
 
 
 
-    /** 
+    /**
      * The description or definition of a job that's doing the transcoding.
      */
     public class JobDefinition {
         public final Transcoder transcoder;
+        public final Node dest;
         public final List<Analyzer> analyzers;
+        public final URI in;
+        public final URI out;
         JobDefinition(Transcoder t) {
             transcoder = t;
             analyzers = new ArrayList<Analyzer>();
+            dest = null;
+            in = null;
+            out = null;
         }
-        JobDefinition(JobDefinition jd) {
+        JobDefinition(JobDefinition jd, Node dest, URI in, URI out) {
             transcoder = jd.transcoder.clone();
             analyzers  = jd.analyzers;
+            this.dest = dest;
+            this.in = in;
+            this.out = out;
         }
 
         public Transcoder getTranscoder() {
@@ -479,7 +381,17 @@
         public List<Analyzer> getAnalyzers() {
             return Collections.unmodifiableList(analyzers);
         }
+        public Node getResultNode() {
+            return dest;
+        }
 
+        public URI getIn() {
+            return in;
+        }
+        public URI getOut() {
+            return out;
+        }
+
         @Override
         public String toString() {
             return "" + transcoder + " " + analyzers;
@@ -488,32 +400,137 @@
 
 
     private static long lastJobNumber = 0;
-    public class Job {
+    public class Job implements Iterable<JobDefinition> {
 
         private final String user;
-        private final int nodeNumber;
+        private final Node node;
+        private final Node mediaprovider;
+        private final Node mediafragment;
         private final BufferedLogger logger;
-        private final int size;
+        private final Map<String, JobDefinition> clones = new 
LinkedHashMap<String, JobDefinition>();
         private final long number = lastJobNumber++;
 
         private int busy = 0;
 
         private Future<Integer> future;
-        private Transcoder transcoder;
+
+        private JobDefinition current;
+
         private Thread thread;
         boolean interrupted = false;
         boolean ready = false;
 
-        public Job(Node node, ChainedLogger chain, int s) {
+
+        public Job(Node node, ChainedLogger chain, Map<String, JobDefinition> 
list) {
             user = node.getCloud().getUser().getIdentifier();
-            nodeNumber = node.getNumber();
+            this.node = node;
             logger = new BufferedLogger();
             logger.setLevel(Level.DEBUG);
             logger.setMaxSize(100);
             logger.setMaxAge(60000);
             chain.addLogger(logger);
-            size = s;
+            // mediafragment if it does not yet exist
+            mediafragment = node.getNodeValue("mediafragment");
+            mediaprovider = node.getNodeValue("mediaprovider");
+            File inFile = new File(FileServlet.getDirectory(), 
node.getStringValue("url"));
+
+            try {
+                synchronized(list) {
+                    for (Map.Entry<String, JobDefinition> entry : 
list.entrySet()) {
+                        JobDefinition jd = entry.getValue();
+                        String id = entry.getKey();
+                        if (jd.transcoder.getFormat() != null) {
+                            Node resultNode = 
getCacheNode(jd.transcoder.getKey());
+                            resultNode.setIntValue("state",  
State.REQUEST.getValue());
+                            resultNode.setStringValue("key", 
jd.transcoder.getKey());
+                            resultNode.setIntValue("format", 
jd.transcoder.getFormat().toInt());
+                            resultNode.setIntValue("codec", 
jd.transcoder.getCodec().toInt());
+                            resultNode.setNodeValue("id",    node);
+                            resultNode.commit();
+
+                            StringBuilder buf = new StringBuilder();
+                            
org.mmbase.storage.implementation.database.DatabaseStorageManager.appendDirectory(buf,
 resultNode.getNumber(), "/");
+                            buf.append(resultNode.getNumber()).append(".");
+                            
buf.append(ResourceLoader.getName(inFile.getName())).append(".").append(jd.transcoder.getFormat().toString().toLowerCase());
+                            String outFileName = buf.toString();
+                            resultNode.setStringValue("url", outFileName);
+                            URI in = inFile.toURI();
+                            File outFile = new 
File(FileServlet.getDirectory(), outFileName.replace("/", File.separator));
+
+
+                            // virtual field actually creates relation
+                            resultNode.setNodeValue("mediaprovider", 
mediaprovider);
+                            resultNode.setNodeValue("mediafragment", 
mediafragment);
+                            resultNode.commit();
+                            logger.info("Created cache node " + 
resultNode.getNumber()  + " for provider " + mediaprovider.getNumber() + " 
fragment " + mediafragment.getNumber());
+                            URI inURI;
+                            if (jd.transcoder.getInId() == null) {
+                                inURI = inFile.toURI();
+                            } else {
+                                inURI = 
clones.get(jd.transcoder.getInId()).getOut();
+                            }
+                            JobDefinition clone = new JobDefinition(jd, 
resultNode, inFile.toURI(), outFile.toURI());
+                            clones.put(id, clone);
+                        } else {
+
+                            JobDefinition clone = new JobDefinition(jd, null, 
inFile.toURI(), null);
+                            logger.info("Cachenode less job" + clone);
+                            clones.put(id, clone);
+
+                        }
+
+                    }
+
+                }
+            } catch (Exception e) {
+                chain.error(e.getClass() + " " + e.getMessage(), e);
+            }
         }
+
+        public Iterator<JobDefinition> iterator() {
+            final Iterator<Map.Entry<String, JobDefinition>> i = 
clones.entrySet().iterator();
+            return new Iterator<JobDefinition>() {
+                public boolean hasNext() {
+                    return i.hasNext();
+                }
+                public void remove() {
+                    throw new UnsupportedOperationException();
+                }
+                public JobDefinition next() {
+                    if (current != null) {
+                        File outFile = new File(FileServlet.getDirectory(), 
current.getResultNode().getStringValue("url").replace("/", File.separator));
+                        current.getResultNode().setLongValue("filesize", 
outFile.length());
+                        current.getResultNode().setIntValue("state",
+                                                            
State.DONE.getValue());
+                        current.getResultNode().commit();
+                    }
+                    current = i.next().getValue();
+                    if (current.transcoder instanceof CommandTranscoder) {
+                        // Get free method
+                        CommandExecutor.Method m = null;
+                        synchronized(executors) {
+                            for (CommandExecutor.Method e : executors) {
+                                if (! e.isInUse()) {
+                                    e.setInUse(true);
+                                    m = e;
+                                    break;
+                                }
+                            }
+                        }
+                        if (m == null) {
+                            LOG.error("There should always be a free 
CommandExecutor. Using LAUCHER now.");
+                        } else {
+                            ((CommandTranscoder) 
current.transcoder).setMethod(m);
+                        }
+                    }
+                    busy++;
+                    current.getResultNode().setIntValue("state", 
State.BUSY.getValue());
+                    return current;
+                }
+
+            };
+        }
+
         public void setFuture(Future<Integer> f) {
             future = f;
         }
@@ -521,6 +538,36 @@
             return logger;
         }
 
+        /**
+         * Gets the node representing the 'cached' stream (the result of a 
conversion).
+         * @param cacheManager
+         * @param node  the original node from which the 'cached' stream was 
created
+         * @param key   representation of the way the stream was created from 
its source
+         * @param logger
+         */
+        protected Node getCacheNode(final String key) {
+
+            for (String cacheManager : new String[] {"streamsourcescaches", 
"videostreamsourcescaches", "audiostreamsourcescaches"}) {
+                final NodeManager caches = 
node.getCloud().getNodeManager(cacheManager);
+                NodeQuery q = caches.createQuery();
+                Queries.addConstraint(q, Queries.createConstraint(q, "id",  
FieldCompareConstraint.EQUAL, node));
+                Queries.addConstraint(q, Queries.createConstraint(q, "key", 
FieldCompareConstraint.EQUAL, key));
+
+                LOG.service("Executing " + q.toSql());
+                NodeList nodes = caches.getList(q);
+                if (nodes.size() > 0) {
+                    return nodes.getNode(0);
+                }
+            }
+            final NodeManager caches = 
node.getCloud().getNodeManager(node.getNodeManager().getProperty("org.mmbase.streams.cachestype"));
+            return caches.createNode();
+        }
+
+
+        public JobDefinition getCurrent() {
+            return current;
+        }
+
         public Thread getThread() {
             return thread;
         }
@@ -549,15 +596,8 @@
             ready = true;
         }
 
-        public void setTranscoder(Transcoder t) {
-            transcoder = t;
-            busy++;
-        }
-        public Transcoder getTranscoder() {
-            return transcoder;
-        }
         public String getProgress() {
-            return "" + busy + "/" + size;
+            return "" + busy + "/" + clones.size();
         }
         public String getUser() {
             return user;
@@ -565,16 +605,16 @@
         public long getNumber() {
             return number;
         }
-        public int getNodeNumber() {
-            return nodeNumber;
+        public Node getNode() {
+            return node;
         }
 
         @Override
         public String toString() {
-            if (transcoder == null) {
-                return number + ":" + user + ":SCHEDULED:" + list;
+            if (current == null) {
+                return number + ":" + user + ":SCHEDULED:" + clones;
             } else {
-                return number + ": " + user + ":" + transcoder + ":" + 
getProgress() + ":" + thread;
+                return number + ": " + user + ":" + current + ":" + 
getProgress() + ":" + thread;
             }
         }
     }

Modified: 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/AbstractTranscoder.java
===================================================================
--- 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/AbstractTranscoder.java
      2009-07-02 10:50:24 UTC (rev 36517)
+++ 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/AbstractTranscoder.java
      2009-07-02 12:52:01 UTC (rev 36518)
@@ -28,22 +28,52 @@
  */
 public abstract class AbstractTranscoder implements Transcoder {
 
+    public static String PACKAGE = "org.mmbase.streams.transcoders.";
+
     public static final Logger LOG = 
Logging.getLoggerInstance(AbstractTranscoder.class);
 
-    public static Transcoder getInstance(String key) throws 
ClassNotFoundException, InstantiationException, IllegalAccessException  {
+    public static Transcoder getInstance(String key) throws 
ClassNotFoundException, InstantiationException, IllegalAccessException, 
NoSuchMethodException, InvocationTargetException  {
         String[] split = key.split(" ", 2);
-        Transcoder trans = (Transcoder) Class.forName(split[0]).newInstance();
-        String[] props = split[1].split(", ");
-        for (String prop : props) {
-            String[] entry = prop.split("=", 2);
-            String k = entry[0];
-            String value = entry[1];
-            org.mmbase.util.xml.Instantiator.setProperty(k, trans.getClass(), 
trans, value);
+        Transcoder trans;
+        {
+            String[] idWithClass = split[0].split(":", 2);
+            if (idWithClass.length == 1) {
+                idWithClass = new String[] { "", split[0]};
+            }
+            Class clazz;
+            try {
+                clazz  = Class.forName(idWithClass[1]);
+            } catch (ClassNotFoundException cnfe) {
+                clazz  = Class.forName(PACKAGE + idWithClass[1]);
+            }
+            Constructor constructor = clazz.getConstructor(String.class);
+
+            trans = (Transcoder) constructor.newInstance(idWithClass[0]);
         }
+        {
+            String[] props = split[1].split(", ");
+            for (String prop : props) {
+                String[] entry = prop.split("=", 2);
+                String k = entry[0];
+                String value = entry[1];
+                org.mmbase.util.xml.Instantiator.setProperty(k, 
trans.getClass(), trans, value);
+            }
+        }
         return trans;
 
     }
 
+    private final String id;
+    private String inId = null;
+
+    protected AbstractTranscoder(String id) {
+        this.id = id;
+    }
+
+    public String getId() {
+        return id;
+    }
+
     protected boolean clone = false;
 
     protected URI in;
@@ -53,6 +83,8 @@
 
     protected Codec  codec = Codec.UNKNOWN;
 
+    protected MimeType  mimeType = MimeType.ANY;
+
     public void setFormat(String f) {
         format = Format.valueOf(f);
     }
@@ -69,8 +101,34 @@
         return codec;
     }
 
+    public MimeType getMimeType() {
+        return mimeType;
+    }
+    public void setMimeType(String m) {
+        mimeType = new MimeType(m);
+    }
+    public String getInId() {
+        return inId;
+    }
+    public void setInId(String i) {
+        inId = i;
+
+    }
+
+
     public  final String getKey() {
-        StringBuilder buf = new StringBuilder(getClass().getName());
+        StringBuilder buf = new StringBuilder();
+        if (getId() != null && getId().length() > 0) {
+            buf.append(getId());
+            buf.append(":");
+        }
+        {
+            String cn = getClass().getName();
+            if (cn.startsWith(PACKAGE)) {
+                cn = cn.substring(PACKAGE.length());
+            }
+            buf.append(cn);
+        }
         buf.append(" ");
         boolean appendedSetting = false;
         Settings settings = getClass().getAnnotation(Settings.class);

Modified: 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/CommandTranscoder.java
===================================================================
--- 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/CommandTranscoder.java
       2009-07-02 10:50:24 UTC (rev 36517)
+++ 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/CommandTranscoder.java
       2009-07-02 12:52:01 UTC (rev 36518)
@@ -31,6 +31,10 @@
     private CommandExecutor.Method method = new CommandExecutor.Method();
 
 
+    public CommandTranscoder(String id) {
+        super(id);
+    }
+
     public void setMethod(CommandExecutor.Method m) {
         method = m;
     }

Modified: 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/FFMpeg2TheoraTranscoder.java
===================================================================
--- 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/FFMpeg2TheoraTranscoder.java
 2009-07-02 10:50:24 UTC (rev 36517)
+++ 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/FFMpeg2TheoraTranscoder.java
 2009-07-02 12:52:01 UTC (rev 36518)
@@ -34,11 +34,14 @@
 
     private static final Logger log = 
Logging.getLoggerInstance(FFMpeg2TheoraTranscoder.class);
 
-    {
+
+    public FFMpeg2TheoraTranscoder(String id) {
+        super(id);
         format = Format.OGV;
         codec  = Codec.THEORA;
     }
 
+
     int videoQuality = 5;
     int keyInt = 64;
     Integer height = null;
@@ -117,9 +120,11 @@
 
 
     public static void main(String[] argv) throws Exception {
-        FFMpeg2TheoraTranscoder ff = new FFMpeg2TheoraTranscoder();
+        FFMpeg2TheoraTranscoder ff = new FFMpeg2TheoraTranscoder("1");
         ff.setHeight(100);
         //ff.setWidth(100);
+        System.out.println("KEY" + ff + " -> " + 
AbstractTranscoder.getInstance(ff.getKey()));
+        System.exit(0);
         CommandTranscoder transcoder = ff.clone();
         Logger logger = Logging.getLoggerInstance("FFMPEG2THEORA");
         ChainedLogger chain = new ChainedLogger(logger);

Modified: 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/FFMpegTranscoder.java
===================================================================
--- 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/FFMpegTranscoder.java
        2009-07-02 10:50:24 UTC (rev 36517)
+++ 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/FFMpegTranscoder.java
        2009-07-02 12:52:01 UTC (rev 36518)
@@ -29,10 +29,13 @@
 
     private static final Logger log = 
Logging.getLoggerInstance(FFMpegTranscoder.class);
 
-    {
+
+    public FFMpegTranscoder(String id) {
+        super(id);
         format = Format.AVI;
     }
 
+
     @Override
     protected  String getCommand() {
         return "ffmpeg";
@@ -72,7 +75,7 @@
 
 
     public static void main(String[] argv) throws Exception {
-        CommandTranscoder transcoder = new FFMpegTranscoder().clone();
+        CommandTranscoder transcoder = new FFMpegTranscoder("1").clone();
         Logger logger = Logging.getLoggerInstance("FFMPEG");
 
         ChainedLogger chain = new ChainedLogger(logger);

Modified: 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/InfiniteTranscoder.java
===================================================================
--- 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/InfiniteTranscoder.java
      2009-07-02 10:50:24 UTC (rev 36517)
+++ 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/InfiniteTranscoder.java
      2009-07-02 12:52:01 UTC (rev 36518)
@@ -26,7 +26,9 @@
 public class InfiniteTranscoder extends AbstractTranscoder {
     private static final Logger LOG = 
Logging.getLoggerInstance(InfiniteTranscoder.class);
     private int seq = 0;
-    {
+
+    public InfiniteTranscoder(String id) {
+        super(id);
         format = Format.UNKNOWN;
     }
 

Added: 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/MimeType.java
===================================================================
--- 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/MimeType.java
                                (rev 0)
+++ 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/MimeType.java
        2009-07-02 12:52:01 UTC (rev 36518)
@@ -0,0 +1,54 @@
+/*
+
+This software is OSI Certified Open Source Software.
+OSI Certified is a certification mark of the Open Source Initiative.
+
+The license (Mozilla version 1.0) can be read at the MMBase site.
+See http://www.MMBase.org/license
+
+*/
+package org.mmbase.streams.transcoders;
+
+import org.mmbase.util.logging.*;
+import org.mmbase.bridge.*;
+
+
+/**
+ *
+ * @author Michiel Meeuwissen
+ */
+
+public class MimeType {
+
+    public static final String STAR = "*";
+    public static final MimeType ANY = new MimeType(STAR, STAR);
+
+    private final String type;
+    private final String subType;
+
+
+    public MimeType(String s) {
+        String[] m = s.split("/", 2);
+        type = m[0];
+        if (m.length > 1) {
+            subType = m[1];
+        } else {
+            subType = STAR;
+        }
+    }
+    public MimeType(String t, String s) {
+        type = t;
+        subType = s;
+    }
+
+    public String getType() {
+        return type;
+    }
+    public String getSubType() {
+        return subType;
+    }
+
+    public String toString() {
+        return type + "/" + subType;
+    }
+}

Added: 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/Recognizer.java
===================================================================
--- 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/Recognizer.java
                              (rev 0)
+++ 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/Recognizer.java
      2009-07-02 12:52:01 UTC (rev 36518)
@@ -0,0 +1,30 @@
+/*
+
+This software is OSI Certified Open Source Software.
+OSI Certified is a certification mark of the Open Source Initiative.
+
+The license (Mozilla version 1.0) can be read at the MMBase site.
+See http://www.MMBase.org/license
+
+*/
+package org.mmbase.streams.transcoders;
+
+import org.mmbase.util.logging.*;
+import java.net.*;
+
+
+/**
+ *
+ * @author Michiel Meeuwissen
+ */
+
+public interface Recognizer extends 
org.mmbase.util.PublicCloneable<Recognizer> {
+
+
+    MimeType getMimeType();
+    void setMimeType(String s);
+
+    void analyze(URI in, Logger logger) throws Exception;
+
+
+}

Added: 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/RecognizerTranscoder.java
===================================================================
--- 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/RecognizerTranscoder.java
                            (rev 0)
+++ 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/RecognizerTranscoder.java
    2009-07-02 12:52:01 UTC (rev 36518)
@@ -0,0 +1,112 @@
+/*
+
+This software is OSI Certified Open Source Software.
+OSI Certified is a certification mark of the Open Source Initiative.
+
+The license (Mozilla version 1.0) can be read at the MMBase site.
+See http://www.MMBase.org/license
+
+*/
+package org.mmbase.streams.transcoders;
+
+import org.mmbase.applications.media.Format;
+import org.mmbase.applications.media.Codec;
+import java.net.*;
+import java.lang.reflect.*;
+import java.io.*;
+import java.util.*;
+import org.mmbase.util.externalprocess.*;
+import org.mmbase.util.WriterOutputStream;
+
+import org.mmbase.util.logging.*;
+
+
+/**
+ * This thin wrapper just represents a 'Recognizer' as a Transcoder. This 
makes administration easier.
+ *
+ * @author Michiel Meeuwissen
+ * @version $Id: AbstractTranscoder.java 36425 2009-06-25 18:26:28Z michiel $
+ */
+public class RecognizerTranscoder implements Transcoder {
+
+    final Recognizer recognizer;
+    protected RecognizerTranscoder(Recognizer rec) {
+        recognizer = rec;
+    }
+
+    public String getId() {
+        return "";
+    }
+
+    protected boolean clone = false;
+
+    protected URI in;
+    protected URI out;
+
+    protected Format format;
+
+    protected Codec  codec = Codec.UNKNOWN;
+
+    protected MimeType  mimeType = MimeType.ANY;
+
+    public void setFormat(String f) {
+        throw new UnsupportedOperationException();
+    }
+
+    public Format getFormat() {
+        return null;
+    }
+
+    public void setCodec(String c) {
+        throw new UnsupportedOperationException();
+    }
+
+    public Codec getCodec() {
+        return null;
+    }
+
+    public MimeType getMimeType() {
+        return recognizer.getMimeType();
+    }
+    public void setMimeType(String m) {
+        recognizer.setMimeType(m);
+    }
+    public String getInId() {
+        return null;
+    }
+    public void setInId(String i) {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public  final String getKey() {
+        return null;
+
+    }
+
+    public final void transcode(final URI in, final URI out, final Logger log) 
throws Exception {
+        if (in == null) throw new IllegalArgumentException();
+        this.in = in;
+        recognizer.analyze(in, log);
+    }
+
+    public URI getIn() {
+        return in;
+    }
+    public URI getOut() {
+        return null;
+    }
+
+    public RecognizerTranscoder clone() {
+        try {
+            RecognizerTranscoder c =  (RecognizerTranscoder) super.clone();
+            c.clone = true;
+            return c;
+        } catch (CloneNotSupportedException cnse) {
+            throw new RuntimeException(cnse);
+        }
+    }
+
+
+
+}

Modified: 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/Transcoder.java
===================================================================
--- 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/Transcoder.java
      2009-07-02 10:50:24 UTC (rev 36517)
+++ 
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/Transcoder.java
      2009-07-02 12:52:01 UTC (rev 36518)
@@ -31,7 +31,13 @@
 
     Codec getCodec();
 
+    String getId();
 
+    MimeType getMimeType();
+
+    String getInId();
+    void setInId(String i);
+
     /**
      *
      */

Modified: 
mmbase/trunk/applications/streams/src/main/resources/org/mmbase/streams/resources/createcaches.xsd
===================================================================
--- 
mmbase/trunk/applications/streams/src/main/resources/org/mmbase/streams/resources/createcaches.xsd
  2009-07-02 10:50:24 UTC (rev 36517)
+++ 
mmbase/trunk/applications/streams/src/main/resources/org/mmbase/streams/resources/createcaches.xsd
  2009-07-02 12:52:01 UTC (rev 36518)
@@ -20,6 +20,7 @@
           <xsd:element ref="localhost" />
           <xsd:element ref="server"  />
         </xsd:choice>
+        <xsd:element ref="sourceanalyzer"   minOccurs="0" 
maxOccurs="unbounded" />
         <xsd:element ref="transcoder" minOccurs="0" maxOccurs="unbounded" />
       </xsd:sequence>
       <xsd:attribute name="name"  type="xsd:string" />
@@ -32,6 +33,9 @@
         <xsd:element ref="class" minOccurs="1" maxOccurs="1" />
         <xsd:element ref="loganalyzer" minOccurs="0" maxOccurs="unbounded" />
       </xsd:sequence>
+      <xsd:attribute name="id"        type="xsd:string" use="required" />
+      <xsd:attribute name="in"        type="xsd:string" />
+      <xsd:attribute name="mimetype"  type="xsd:string" />
     </xsd:complexType>
   </xsd:element>
 

Modified: 
mmbase/trunk/applications/streams/src/main/webapp/mmbase/components/streams/admin.jspx
===================================================================
--- 
mmbase/trunk/applications/streams/src/main/webapp/mmbase/components/streams/admin.jspx
      2009-07-02 10:50:24 UTC (rev 36517)
+++ 
mmbase/trunk/applications/streams/src/main/webapp/mmbase/components/streams/admin.jspx
      2009-07-02 12:52:01 UTC (rev 36518)
@@ -21,8 +21,8 @@
       <table summary="configuration">
         <caption>Configuration</caption>
         <c:forEach 
items="${status.current.dataType.commitProcessor.processors[2].configuration}" 
var="jobdef">
-          <tr><td>${jobdef.transcoder}</td></tr>
-          <tr><td>${jobdef.analyzers}</td></tr>
+          <tr><td>${jobdef.value.transcoder}</td></tr>
+          <tr><td>${jobdef.value.analyzers}</td></tr>
         </c:forEach>
       </table>
     </mm:fieldlist>

Modified: 
mmbase/trunk/applications/streams/src/main/webapp/mmbase/components/streams/alljobs.jspx
===================================================================
--- 
mmbase/trunk/applications/streams/src/main/webapp/mmbase/components/streams/alljobs.jspx
    2009-07-02 10:50:24 UTC (rev 36517)
+++ 
mmbase/trunk/applications/streams/src/main/webapp/mmbase/components/streams/alljobs.jspx
    2009-07-02 12:52:01 UTC (rev 36518)
@@ -19,17 +19,17 @@
   <ul>
     <mm:listfunction set="streams" name="runningJobs" id="job">
       <li>
-        <span>${_} (${_.progress}). Node ${_.nodeNumber}.</span>
+        <span>${_} (${_.progress}). Node ${_.node.number}.</span>
         <mm:may action="cancel_jobs">
           <mm:link>
-            <mm:param name="cancel">${job.nodeNumber}</mm:param>
+            <mm:param name="cancel">${job.node.number}</mm:param>
             <a href="${_}">Cancel this job</a>
           </mm:link>
         </mm:may>
         <p>
-          <span class="in">${_.transcoder.in}</span>
+          <span class="in">${_.current.in}</span>
           <jsp:text> -&amp;gt; </jsp:text>
-          <span class="out">${_.transcoder.out}</span>
+          <span class="out">${_.current.out}</span>
         </p>
         <div class="log">
           <pre>

_______________________________________________
Cvs mailing list
[email protected]
http://lists.mmbase.org/mailman/listinfo/cvs

Reply via email to