Author: andre
Date: 2010-03-25 16:14:19 +0100 (Thu, 25 Mar 2010)
New Revision: 41615
Added:
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/SegmenterAnalyzer.java
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/SegmenterTranscoder.java
Modified:
mmbase/trunk/applications/streams/src/main/config/streams/createcaches.xml
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/createcaches/JobCallable.java
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/createcaches/Processor.java
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/createcaches/Result.java
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/createcaches/TranscoderResult.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/AnalyzerUtils.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/FFMpegRecognizer.java
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/FFMpegTranscoder.java
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/urlcomposers/ImagesURLComposer.java
mmbase/trunk/applications/streams/src/main/webapp/mmbase/components/streams/job.jspx
Log:
porting differences with 1.9
Modified:
mmbase/trunk/applications/streams/src/main/config/streams/createcaches.xml
===================================================================
--- mmbase/trunk/applications/streams/src/main/config/streams/createcaches.xml
2010-03-25 14:51:40 UTC (rev 41614)
+++ mmbase/trunk/applications/streams/src/main/config/streams/createcaches.xml
2010-03-25 15:14:19 UTC (rev 41615)
@@ -46,6 +46,65 @@
<loganalyzer name="org.mmbase.streams.transcoders.FFMpeg2TheoraAnalyzer" />
</transcoder>
+
+ <!-- example config for ts streams over cellular networks (for iPhone etc.)
-->
+<!--
+ <transcoder
+ label="lo"
+ mimetype="video/*" id="v1">
+ <class name="org.mmbase.streams.transcoders.FFMpegTranscoder">
+
+ <param name="format">ts</param>
+ <param name="forceFormat">mpegts</param>
+ <param name="vcodec">libx264</param>
+ <param name="framesPerSecond">25</param>
+ <param name="bitrate">96k</param>
+ <param name="acodec">libmp3lame</param>
+ <param name="abitrate">48000</param>
+ <param name="audioChannels">2</param>
+ <param name="async">2</param>
+ <param name="width">320</param>
+ <param name="height">240</param>
+
+ <param name="-flags">+loop</param>
+ <param name="-cmp">+chroma</param>
+ <param name="-partitions">+parti4x4+partp8x8+partb8x8</param>
+ <param name="-subq">5</param>
+ <param name="-trellis">1</param>
+ <param name="-refs">1</param>
+ <param name="-coder">0</param>
+ <param name="-me_range">16</param>
+ <param name="-keyint_min">25</param>
+ <param name="-sc_threshold">40</param>
+ <param name="-i_qfactor">0.71</param>
+ <param name="-bt">200k</param>
+ <param name="-maxrate">96k</param>
+ <param name="-bufsize">96k</param>
+ <param name="-rc_eq">'blurCplx^(1-qComp)'</param>
+ <param name="-qcomp">0.6</param>
+ <param name="-qmin">10</param>
+ <param name="-qmax">51</param>
+ <param name="-qdiff">4</param>
+ <param name="-level">30</param>
+ <param name="-aspect">320:240</param>
+ <param name="-g">30</param>
+
+ </class>
+ <loganalyzer name="org.mmbase.streams.transcoders.FFMpegAnalyzer" />
+ </transcoder>
+
+ <transcoder
+ label="lo"
+ mimetype="video/*" in="v1" id="v2">
+ <class name="org.mmbase.streams.transcoders.SegmenterTranscoder">
+ <param name="format">ts</param>
+ <param name="duration">10</param>
+ <param name="httpPrefix">http://www.openimages.eu/</param>
+ </class>
+ <loganalyzer name="org.mmbase.streams.transcoders.SegmenterAnalyzer" />
+ </transcoder>
+ -->
+
<!--
<transcoder mimetype="audio/*" in="v1" id="v3">
<class name="org.mmbase.streams.transcoders.FFMpeg2TheoraTranscoder">
Modified:
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/createcaches/JobCallable.java
===================================================================
---
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/createcaches/JobCallable.java
2010-03-25 14:51:40 UTC (rev 41614)
+++
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/createcaches/JobCallable.java
2010-03-25 15:14:19 UTC (rev 41615)
@@ -116,7 +116,7 @@
Result current = thisJob.getCurrent();
if (current == null || current.isReady()) {
if (iterator.hasNext()) {
- LOG.debug("next !");
+ //LOG.debug("next !");
iterator.next();
}
current = thisJob.getCurrent();
@@ -125,7 +125,7 @@
if (current.isReady()) {
thisJob.ready();
Processor.runningJobs.remove(thisJob.getNode().getNumber());
- LOG.info("1: returning resultCount: " + resultCount);
+ //LOG.info("1: returning resultCount: " + resultCount);
return resultCount;
}
@@ -136,7 +136,7 @@
thisJob.submit(this);
} catch (Exception e) {
}
- LOG.info("2: returning resultCount: " + resultCount);
+ //LOG.info("2: returning resultCount: " + resultCount);
return resultCount;
}
result = current;
@@ -151,18 +151,18 @@
analyzerLoggers.add(al);
logger.addLogger(al);
}
+
assert in != null;
-
try {
jd.transcoder.transcode(in, out, logger);
for (AnalyzerLogger al : analyzerLoggers) {
al.getAnalyzer().ready(thisJob.getNode(),
result.getDestination());
}
-
resultCount++;
result.ready();
logger.info("RESULT " + thisJob + "(" +
thisJob.getNode().getNodeManager().getName() + ":" +
thisJob.getNode().getNumber() + "):" + result);
+
if (thisJob.isInterrupted() ||
Thread.currentThread().isInterrupted()){
logger.info("Interrupted");
break;
@@ -196,7 +196,7 @@
logger.info("FINALLY " + resultCount);
thisJob.notifyAll(); // notify waiters
}
- logger.info("3: returning resultCount: " + resultCount);
+ //logger.info("3: returning resultCount: " + resultCount);
return resultCount;
}
Modified:
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/createcaches/Processor.java
===================================================================
---
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/createcaches/Processor.java
2010-03-25 14:51:40 UTC (rev 41614)
+++
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/createcaches/Processor.java
2010-03-25 15:14:19 UTC (rev 41615)
@@ -36,6 +36,7 @@
import org.mmbase.util.externalprocess.CommandExecutor;
import org.mmbase.util.logging.*;
import org.mmbase.util.xml.*;
+
import org.w3c.dom.Document;
import org.w3c.dom.Element;
Modified:
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/createcaches/Result.java
===================================================================
---
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/createcaches/Result.java
2010-03-25 14:51:40 UTC (rev 41614)
+++
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/createcaches/Result.java
2010-03-25 15:14:19 UTC (rev 41615)
@@ -27,7 +27,6 @@
import org.mmbase.util.MimeType;
-
/**
* When executing an actual {...@link JobDefinition} the result is contained
in an object like this.
* @author Michiel Meeuwissen
Modified:
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/createcaches/TranscoderResult.java
===================================================================
---
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/createcaches/TranscoderResult.java
2010-03-25 14:51:40 UTC (rev 41614)
+++
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/createcaches/TranscoderResult.java
2010-03-25 15:14:19 UTC (rev 41615)
@@ -24,9 +24,9 @@
import java.io.File;
import java.net.URI;
+import org.mmbase.util.MimeType;
import org.mmbase.applications.media.State;
import org.mmbase.bridge.Node;
-import org.mmbase.util.MimeType;
import org.mmbase.util.logging.Logger;
import org.mmbase.util.logging.Logging;
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
2010-03-25 14:51:40 UTC (rev 41614)
+++
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/AbstractTranscoder.java
2010-03-25 15:14:19 UTC (rev 41615)
@@ -21,16 +21,19 @@
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.net.URI;
-
-import org.mmbase.applications.media.Codec;
-import org.mmbase.applications.media.Format;
+import java.io.*;
+import java.util.*;
+import org.mmbase.util.externalprocess.*;
+import org.mmbase.util.WriterOutputStream;
import org.mmbase.util.MimeType;
-import org.mmbase.util.logging.Logger;
-import org.mmbase.util.logging.Logging;
+import org.mmbase.util.logging.*;
+
/**
* Base transcoder for others.
*
@@ -46,7 +49,7 @@
public static Transcoder getInstance(String key) throws
ClassNotFoundException, InstantiationException, IllegalAccessException,
NoSuchMethodException, InvocationTargetException {
String[] split = key.split(" ", 2);
Transcoder trans;
- {
+ { // parse split[0] (a class name) to instantiate object
String[] idWithClass = split[0].split(":", 2);
if (idWithClass.length == 1) {
idWithClass = new String[] { "", split[0]};
@@ -65,7 +68,7 @@
trans = (Transcoder) clazz.newInstance();
}
}
- {
+ { // parse split[1] to set properties on it.
String[] props = split[1].split(", ");
for (String prop : props) {
String[] entry = prop.split("=", 2);
@@ -122,7 +125,7 @@
*
* The implementation depends on {...@link Settings} annotations to be set
on the classes.
*/
- public final String getKey() {
+ public String getKey() {
StringBuilder buf = new StringBuilder();
{
String cn = getClass().getName();
@@ -171,7 +174,7 @@
return buf.toString();
}
- public final void transcode(final URI in, final URI out, final Logger log)
throws Exception {
+ public void transcode(final URI in, final URI out, final Logger log)
throws Exception {
if (in == null) throw new IllegalArgumentException(toString());
if (out == null) throw new IllegalArgumentException(toString());
this.in = in;
Modified:
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/AnalyzerUtils.java
===================================================================
---
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/AnalyzerUtils.java
2010-03-25 14:51:40 UTC (rev 41614)
+++
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/AnalyzerUtils.java
2010-03-25 15:14:19 UTC (rev 41615)
@@ -29,6 +29,8 @@
import org.mmbase.bridge.Cloud;
import org.mmbase.bridge.Node;
import org.mmbase.util.MimeType;
+
+
import org.mmbase.util.logging.*;
/**
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
2010-03-25 14:51:40 UTC (rev 41614)
+++
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/CommandTranscoder.java
2010-03-25 15:14:19 UTC (rev 41615)
@@ -45,8 +45,7 @@
private String path =
org.mmbase.util.ApplicationContextReader.getCachedProperties(getClass().getName()).get("path");
- // TODO
- private Map<String, String> moreOptions = new HashMap<String, String>();
+ private Map<String, String> moreOptions = new LinkedHashMap<String,
String>();
public CommandTranscoder() {
LOG.service("" + getClass().getName() + " path:" + path);
@@ -79,6 +78,28 @@
return new LoggerWriter(log, Level.ERROR);
}
+ /**
+ * Overrides the generation of a key in {...@link AbstractTranscoder} to
add extra transcoding
+ * parameters that were not set by {...@link Settings} annotations on the
transcoders.
+ */
+ public final String getKey() {
+ StringBuilder key = new StringBuilder( super.getKey() );
+ boolean appendedSetting = false;
+ if (key.indexOf(", ") > 0) {
+ appendedSetting = true;
+ }
+
+ for (Map.Entry<String, String> e : moreOptions.entrySet()) {
+ if (appendedSetting) {
+ key.append(", ");
+ }
+ key.append(e.getKey()).append("=").append(e.getValue());
+ appendedSetting = true;
+ }
+
+ return key.toString();
+ }
+
protected void transcode(final Logger log) throws Exception {
OutputStream outStream = new WriterOutputStream(getOutputWriter(log),
System.getProperty("file.encoding"));
OutputStream errStream = new WriterOutputStream(getErrorWriter(log),
System.getProperty("file.encoding"));
@@ -91,23 +112,29 @@
p += File.separator;
}
+ List<String> args = new ArrayList<String>(
Arrays.asList(getArguments()) );
+ List<String> extra = new ArrayList<String>();
+ for (Map.Entry<String, String> e : moreOptions.entrySet()) {
+ extra.add(e.getKey());
+ extra.add(e.getValue());
+ }
+ int pos = args.size() - 2; // last argument is outfile
+ if (pos > -1) {
+ if (!extra.isEmpty()) args.addAll(pos, extra);
+ } else {
+ LOG.error("Not enough arguments, need at least in- and outfile.");
+ }
if (LOG.isServiceEnabled()) {
- LOG.service("Calling (" + method + ") " + p + getCommand() + " " +
Arrays.asList(getArguments()));
+ LOG.service("Calling (" + method + ") " + p + getCommand() + " " +
args);
}
-
- // TODO Add support for 'moreOptions'
- // Here, but also in getKey.
-
- CommandExecutor.execute(outStream, errStream, method, p +
getCommand(), getArguments());
+ CommandExecutor.execute(outStream, errStream, method, p +
getCommand(), args.toArray(new String[args.size()]));
outStream.close();
errStream.close();
}
-
public CommandTranscoder clone() {
return (CommandTranscoder) super.clone();
}
-
}
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
2010-03-25 14:51:40 UTC (rev 41614)
+++
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/FFMpeg2TheoraTranscoder.java
2010-03-25 15:14:19 UTC (rev 41615)
@@ -35,7 +35,9 @@
/**
- * A trancoder base on an external command, like <code>ffmpeg</code> or
<code>ffmpeg2theora</code>
+ * This transcoder uses the command <code>ffmpeg2theora</code>. Possible
parameters to be set in
+ * 'createcaches.xml' are: videoQuality (--videoquality), keyInt (--keyint),
height (-y) and width (-x).
+ * Others can be added but will be at the end of the commands parameters.
*
* @author Michiel Meeuwissen
* @version $Id$
@@ -43,16 +45,13 @@
@Settings({"videoQuality", "keyInt", "height", "width"})
public class FFMpeg2TheoraTranscoder extends CommandTranscoder {
-
private static final Logger log =
Logging.getLoggerInstance(FFMpeg2TheoraTranscoder.class);
-
public FFMpeg2TheoraTranscoder() {
format = Format.OGV;
codec = Codec.THEORA;
}
-
int videoQuality = 5;
int keyInt = 64;
Integer height = null;
@@ -103,7 +102,6 @@
args.add("-y"); args.add("" + height);
}
-
args.add(inFile.toString());
return args.toArray(new String[args.size()]);
Modified:
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/FFMpegRecognizer.java
===================================================================
---
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/FFMpegRecognizer.java
2010-03-25 14:51:40 UTC (rev 41614)
+++
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/FFMpegRecognizer.java
2010-03-25 15:14:19 UTC (rev 41615)
@@ -25,12 +25,14 @@
import java.net.URI;
import org.mmbase.util.MimeType;
+
import org.mmbase.util.WriterOutputStream;
import org.mmbase.util.externalprocess.CommandExecutor;
import org.mmbase.util.logging.*;
/**
+ * A recognizer that uses FFmpeg to analyze media.
*
* @author Michiel Meeuwissen
* @version $Id: FFMpegRecognizer.java 36518 2009-07-02 12:52:01Z michiel $
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
2010-03-25 14:51:40 UTC (rev 41614)
+++
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/FFMpegTranscoder.java
2010-03-25 15:14:19 UTC (rev 41615)
@@ -33,15 +33,23 @@
/**
+ * The transcoder that uses <code>ffmpeg</code> to transcode media. Possible
parameters to be set in
+ * 'createcaches.xml' are: format, forceFormat (-f), acodec (-acodec), vcodec
(-vcodec),
+ * vpre (-vpre), aq (-aq), ab (-ab), bitrate or b (-b), async (-async),
framesPerSecond or
+ * r (-r), audioChannels or ac (-ac),
+ * width and height (combined to -s).
+ * Others can be added as extra parameters but will be at the end of the
commands parameters. See the
+ * documentation for FFmpeg for more information.
*
* @author Michiel Meeuwissen
* @version $Id$
*/
-...@settings({"format", "acodec", "vcodec", "vpre", "aq", "ab", "b", "async",
"r", "ac", "width", "height"})
+...@settings({"format", "forceFormat", "acodec", "vcodec", "vpre", "aq", "ab",
"b", "async", "r", "ac", "width", "height"})
public class FFMpegTranscoder extends CommandTranscoder {
private static final Logger log =
Logging.getLoggerInstance(FFMpegTranscoder.class);
+ String forceFormat = null;
String acodec = null;
String vcodec = null;
String vpre = null;
@@ -55,6 +63,10 @@
Integer width = null;
Integer height = null;
+ public void setForceFormat(String f) {
+ forceFormat = f;
+ }
+
/* Audio codec to use -acodec */
public void setAcodec(String a) {
acodec = a;
@@ -155,18 +167,36 @@
args.add("-i");
args.add(inFile.toString());
- if (acodec != null) {
- args.add("-acodec");
- args.add(acodec);
+ if (forceFormat != null) {
+ args.add("-f");
+ args.add(forceFormat);
}
+ // video
if (vcodec != null) {
args.add("-vcodec");
args.add(vcodec);
}
+ if (b != null) {
+ args.add("-b");
+ args.add(b);
+ }
+ if (r != null) {
+ args.add("-r");
+ args.add(r);
+ }
if (vpre != null) {
args.add("-vpre");
args.add(vpre);
}
+ if (width != null && height != null) {
+ args.add("-s");
+ args.add(width + "x" + height);
+ }
+ // audio
+ if (acodec != null) {
+ args.add("-acodec");
+ args.add(acodec);
+ }
if (aq != null) {
args.add("-aq");
args.add(aq);
@@ -175,25 +205,18 @@
args.add("-ab");
args.add(ab);
}
- if (b != null) {
- args.add("-b");
- args.add(b);
- }
- if (r != null) {
- args.add("-r");
- args.add(r);
- }
if (ac != null) {
args.add("-ac");
args.add(ac);
}
- if (width != null && height != null) {
- args.add("-s");
- args.add(width + "x" + height);
+
+ if (async != null) {
+ args.add("-async");
+ args.add(async);
}
+ args.add("-y"); // overwrite
args.add(outFile.toString());
- args.add("-y"); // overwrite
return args.toArray(new String[args.size()]);
}
Added:
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/SegmenterAnalyzer.java
===================================================================
---
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/SegmenterAnalyzer.java
(rev 0)
+++
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/SegmenterAnalyzer.java
2010-03-25 15:14:19 UTC (rev 41615)
@@ -0,0 +1,152 @@
+/*
+
+This file is part of the MMBase Streams application,
+which is part of MMBase - an open source content management system.
+ Copyright (C) 2009 André van Toly, Michiel Meeuwissen
+
+MMBase Streams is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+MMBase Streams is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with MMBase. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+package org.mmbase.streams.transcoders;
+
+import java.util.regex.*;
+import java.util.*;
+import java.io.*;
+
+import org.mmbase.servlet.FileServlet;
+import org.mmbase.bridge.*;
+
+import org.mmbase.util.logging.*;
+
+
+/**
+ * Analyzes <code>segmenter</code> output during its job, changes url field to
m3u8 index file when
+ * ready and rewrites m3u8 to removed full paths.
+ *
+ * @author André van Toly
+ * @version $Id: SegmenterAnalyzer.java 40036 2009-11-30 20:27:39Z andre $
+ */
+public class SegmenterAnalyzer implements Analyzer {
+
+ private static final Logger LOG =
Logging.getLoggerInstance(SegmenterAnalyzer.class);
+
+ public int getMaxLines() {
+ return Integer.MAX_VALUE;
+ }
+
+ // TODO: progress matcher
+ // private static final Pattern PROGRESS = Pattern.compile("\\s*(.*?)
audio: ([0-9]+)kbps video: ([0-9]+)kbps, time remaining: .*");
+
+ private ChainedLogger log = new ChainedLogger(LOG);
+
+ private AnalyzerUtils util = new AnalyzerUtils(log);
+
+ private List<Throwable> errors =new ArrayList<Throwable>();
+
+ public void addThrowable(Throwable t) {
+ errors.add(t);
+ }
+
+ public void addLogger(Logger logger) {
+ log.addLogger(logger);
+ }
+
+ public void analyze(String l, Node source, Node des) {
+ synchronized(util) {
+ Cloud cloud = source.getCloud();
+
+ if (util.duration(l, source, des)) {
+ return;
+ }
+
+ if (util.dimensions(l, source, des)) {
+ return;
+ }
+
+ if (util.audio(l, source, des)) {
+ return;
+ }
+
+ // TODO: progress matcher
+ /*
+ {
+ Matcher m = PROGRESS.matcher(l);
+ if (m.matches()) {
+ long pos = util.getLength(m.group(1));
+ long audioBitrate = Integer.parseInt(m.group(2));
+ long videoBitrate = Integer.parseInt(m.group(3));
+ bits += ((double) (audioBitrate + videoBitrate)) *
((double) pos - prevPos) * 1000;
+ //System.out.println("" + pos + "ms " + (audioBitrate +
videoBitrate) + " -> " + (bits / pos) + " " + (100 * pos / length) + " %");
+
+ prevPos = pos;
+ }
+ }
+ */
+ }
+ }
+
+ public void ready(Node sourceNode, Node destNode) {
+ synchronized(util) {
+ String url = destNode.getStringValue("url");
+ url = url.substring(0, url.lastIndexOf('.')) + ".m3u8";
+ destNode.setStringValue("url", url);
+
+ if (FileServlet.getInstance() != null) {
+
+ String filesDirectory = FileServlet.getDirectory().toString();
+ if (!filesDirectory.endsWith("/")) {
+ filesDirectory = filesDirectory + "/";
+ }
+ File index = new File(filesDirectory + url);
+ File temp = new File(filesDirectory + url + ".tmp");
+
+ try {
+ BufferedReader in = new BufferedReader(new
FileReader(index));
+ PrintWriter pw = new PrintWriter(new FileWriter(temp));
+
+ String line = null;
+ while((line = in.readLine()) != null) {
+ if (line.indexOf(filesDirectory) > -1) {
+ line = line.replace(filesDirectory, "");
+ }
+ pw.println(line);
+ }
+ in.close();
+ pw.close();
+
+ // Delete original and rename new one
+ if (!index.delete()) log.error("Could not delete file: " +
index.toString());
+ if (!temp.renameTo(index)) log.error("Could not rename
file to: " + index.toString());
+
+ LOG.debug("Rewrote m3u8 indexfile: " + index);
+ } catch (java.io.IOException ioe) {
+ LOG.error("Could not rewrite m3u8 indexfile: " + ioe);
+ }
+
+ }
+ }
+
+ }
+
+ public SegmenterAnalyzer clone() {
+ try {
+ return (SegmenterAnalyzer) super.clone();
+ } catch (CloneNotSupportedException cnfe) {
+ // doesn't happen
+ return null;
+ }
+ }
+
+}
Added:
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/SegmenterTranscoder.java
===================================================================
---
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/SegmenterTranscoder.java
(rev 0)
+++
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/transcoders/SegmenterTranscoder.java
2010-03-25 15:14:19 UTC (rev 41615)
@@ -0,0 +1,144 @@
+/*
+
+This file is part of the MMBase Streams application,
+which is part of MMBase - an open source content management system.
+ Copyright (C) 2009 André van Toly, Michiel Meeuwissen
+
+MMBase Streams is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+MMBase Streams is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with MMBase. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+package org.mmbase.streams.transcoders;
+
+import java.net.*;
+import java.io.*;
+import java.util.*;
+import java.util.regex.*;
+
+import org.mmbase.module.core.MMBaseContext;
+import org.mmbase.bridge.*;
+import org.mmbase.bridge.util.*;
+import org.mmbase.util.logging.*;
+import org.mmbase.servlet.FileServlet;
+
+import org.mmbase.applications.media.Codec;
+import org.mmbase.applications.media.Format;
+
+
+/**
+ * The transcoder that uses <code>segmenter</code> to create segments of a
stream including their
+ * m3u8 index file to be distributed over a cellular network.
+ * The source of the segmenter can be found:
http://svn.assembla.com/svn/legend/segmenter/
+ * It accepts the following arguments:
+ * segmenter sample_low.ts 10 sample_low sample_low.m3u8
http://www.openimages.eu/
+ * The input file, output prefix and index prefix arguments are automatically
filled,
+ * specify segment duration (default 10 sec.) and httpPrefix (hostname) in
'createcaches.xml'.
+ *
+ * @author André van Toly
+ * @version $Id: SegmenterTranscoder.java 41564 2010-03-22 19:42:15Z andre $
+ */
+...@settings({"duration", "httpPrefix"})
+public class SegmenterTranscoder extends CommandTranscoder {
+
+ private static final Logger log =
Logging.getLoggerInstance(SegmenterTranscoder.class);
+
+
+ @Override
+ protected LoggerWriter getErrorWriter(Logger log) {
+ // ffmpeg write also non-errors to stderr, so lets not log on ERROR,
but on SERVICE.
+ // also pluging an error-detector here.
+ return new LoggerWriter(new ChainedLogger(log, new
ErrorDetector(Pattern.compile("\\s*Unknown encoder.*"))), Level.SERVICE);
+ }
+
+ int duration = 10;
+ String httpPrefix = "http://localhost:8080/";
+
+ public SegmenterTranscoder() {
+ format = Format.TS;
+ codec = Codec.H264;
+ }
+
+ public void setDuration(int d) {
+ duration = d;
+ }
+
+ public void setHttpPrefix(String h) {
+ httpPrefix = h;
+ }
+
+ @Override
+ protected String getCommand() {
+ return "segmenter";
+ }
+
+ @Override
+ protected String[] getArguments() {
+ if (! in.getScheme().equals("file")) throw new
UnsupportedOperationException();
+ if (! out.getScheme().equals("file")) throw new
UnsupportedOperationException();
+
+ File inFile = new File(in.getPath());
+ File outFile = new File(out.getPath());
+
+ //String filesDirectory = FileServlet.getDirectory().toString();
+ String filesPath = FileServlet.getBasePath("files");
+ if (filesPath.startsWith("/")) {
+ filesPath = filesPath.substring(1);
+ }
+
+ String outStr = outFile.toString();
+ String file_prefix = outStr.substring(0, outStr.lastIndexOf('.'));
+ String index_file = file_prefix + ".m3u8";
+
+ if (log.isDebugEnabled()) {
+ log.debug("filesPath: " + filesPath);
+ log.debug("file_prefix: " + file_prefix);
+ log.debug("index_file: " + index_file);
+ }
+
+ List<String> args = new ArrayList<String>();
+
+ args.add(inFile.toString());
+ args.add("" + duration);
+ args.add(file_prefix);
+ args.add(index_file);
+ args.add(httpPrefix + filesPath);
+
+ //args.add(out);
+
+ return args.toArray(new String[args.size()]);
+ }
+
+ private static final Pattern PROGRESS = Pattern.compile(".*time
remaining.*");
+
+ @Override
+ protected LoggerWriter getOutputWriter(final Logger log) {
+ LoggerWriter w = new LoggerWriter(log, Level.SERVICE) {
+ @Override
+ public Level getLevel(String line) {
+ if (PROGRESS.matcher(line).matches()) {
+ return Level.DEBUG;
+ }
+ return null;
+ }
+ };
+
+ return w;
+ }
+
+ @Override
+ public SegmenterTranscoder clone() {
+ return (SegmenterTranscoder) super.clone();
+ }
+
+}
Modified:
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/urlcomposers/ImagesURLComposer.java
===================================================================
---
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/urlcomposers/ImagesURLComposer.java
2010-03-25 14:51:40 UTC (rev 41614)
+++
mmbase/trunk/applications/streams/src/main/java/org/mmbase/streams/urlcomposers/ImagesURLComposer.java
2010-03-25 15:14:19 UTC (rev 41615)
@@ -23,6 +23,7 @@
package org.mmbase.streams.urlcomposers;
import org.mmbase.applications.media.Format;
+import org.mmbase.util.MimeType;
import org.mmbase.applications.media.State;
import org.mmbase.applications.media.urlcomposers.FragmentURLComposer;
import org.mmbase.module.builders.ImageCaches;
@@ -30,7 +31,6 @@
import org.mmbase.module.core.MMBase;
import org.mmbase.module.core.MMObjectNode;
import org.mmbase.streams.builders.ImageSources;
-import org.mmbase.util.MimeType;
import org.mmbase.util.images.Dimension;
import org.mmbase.util.images.Factory;
import org.mmbase.util.logging.Logger;
Modified:
mmbase/trunk/applications/streams/src/main/webapp/mmbase/components/streams/job.jspx
===================================================================
---
mmbase/trunk/applications/streams/src/main/webapp/mmbase/components/streams/job.jspx
2010-03-25 14:51:40 UTC (rev 41614)
+++
mmbase/trunk/applications/streams/src/main/webapp/mmbase/components/streams/job.jspx
2010-03-25 15:14:19 UTC (rev 41615)
@@ -47,7 +47,7 @@
<div class="log">
<h4>Job ${_.number} log</h4>
<pre>
- <jsp:text>${_.logger.debugList}</jsp:text>
+ <jsp:text>${mm:escape('text/xml', _.logger.debugList)}</jsp:text>
</pre>
</div>
_______________________________________________
Cvs mailing list
[email protected]
http://lists.mmbase.org/mailman/listinfo/cvs