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
Cvs@lists.mmbase.org
http://lists.mmbase.org/mailman/listinfo/cvs

Reply via email to