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> -&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