Friday, 25 July 2014

FFmpeg

 
Generelle Syntax: ffmpeg [global options] [[infile options][‘-i’ infile]]... {[outfile options] outfile}...
 

Allgemeine Optionen

​Option ​Beschreibung ​Beispiel
​-i ​Bestimmt die Quelldatei (Input-File) und listet Informationen (Metadaten, Bitrate, Codierung, etc. ) über die Datei auf ​ffmpeg -i lala.mp3
-codecs​ ​Listet alle verfügbaren Codecs auf ffmpeg -codecs
-formats​ ​Listet alle verfügbaren Formate auf ffmpeg -formats
 

Wichtige Audio-Optionen

​Option Beschreibung​ ​Beispiel
​-acodec ​Der Audio-Codec mit dem die Zieldatei codiert werden soll, z.B. libvorbis, libmp3lame

Um den Codec der Quelldatei beizubehalten kann man den speziellen Wert 'copy' verwenden - es findet also keine Transcodierung statt: -acodec copy
​ffmpeg -i lala.mp3 -acodec libvorbis lala.ogg
-ab​ ​Die Bitrate mit der die Zieldatei kodiert wird. Eine geringere Bitrate veringert die Dateigröße aber auch die Qualität.

Es macht keine Sinn eine höhere Bitrate für die Zieldatei zu definieren als die Quelldatei hat.
​ffmpeg -i zzz.mp3 -ab 64k  zzz2.mp3
​-aq ​Die Audioqualität; für codecs mit variabler Bitrate
-ar​ ​Die Sampling Frequency in Hertz.

Es macht keine Sinn eine höhere Frequenz für die Zieldatei zu definieren als die Quelldatei hat.
​ffmpeg -i zzz.mp3 -ar 22050 -ab 96k zzz2.mp3
-ss ​When used as an input option (before -i), seeks in this input file to position. When used as an output option (before an output filename), decodes but discards input until the timestamps reach position. This is slower, but more accurate. Position may be either in seconds or in hh:mm:ss[.xxx] form. ffmpeg -ss 00:00:30.00 -t 25 -i bar.mp3 -acodec copy bar-new.mp3
​-t ​Stop writing the output after its duration reaches duration. duration may be a number in seconds, or in hh:mm:ss[.xxx] form.
​-ac ​Set the number of audio channels. For output streams it is set by default to the number of input audio channels. ​ffmpeg -i zzz.mp3 -ac 1 zzz2.mp3
 

Wichtige Video-Optionen

​Option ​Beschreibung ​Beispiel
-b​ ​Bitrate ​-b 2000k
-vcodec​ Der Video-Codec ​-vcodec mpeg4
​-vcodec copy
-s​ ​Bildgröße ​-s 320x240
-s xga
-aspect​ ​-aspect 4:3
​-target ​Vordefinierte targets (All the format options (bitrate, codecs, buffer sizes) are then set automatically) ​-target ntsc-dvd
-r​ ​Frame rate ​-r 10
​-f ​Container format ​-f avi
-ss​ When used as an input option (before -i), seeks in this input file to position. When used as an output option (before an output filename), decodes but discards input until the timestamps reach position. This is slower, but more accurate. Position may be either in seconds or in hh:mm:ss[.xxx] form. ​Extract image: Einen Frame bei Sekunde fünf über eine Sekunde (bei einer Famerate von einem Frame pro Sekunde) mit einer Größe von 320x240 extrahieren
-r 1 -t 1 -ss 5 -s 320x240
​-t Stop writing the output after its duration reaches duration. duration may be a number in seconds, or in hh:mm:ss[.xxx] form.

A FFmpeg Tutorial For Beginners
Using ffmpeg to manipulate audio and video files
FFmpeg – the swiss army knife of Internet Streaming

Tuesday, 8 July 2014

Remove a single entry from a MyBatis cache programatically

MyBatis automatically flushes its cache on a insert/update/delete statement. But what if you need to flush a item from the cache because its database representation has been changed by a different application? Here is how to remove a single entry from a MyBatis cache programatically:


public Object removeCacheEntry(SqlSession sqlSession, String cacheId, String mappingName, Object parameterObject) {
    Object removedObject = null;
    Cache cache = getCache(sqlSession, cacheId);
    if (cache != null) {
        CacheKey cacheKey = getCacheKey(sqlSession, mappingName, parameterObject);
        if (cacheKey != null) {
            removedObject = cache.removeObject(cacheKey);
            logger.info("Remove from cache: {} by key {}", removedObject, cacheKey);
        }
    }
    return removedObject;
}

private Cache getCache(SqlSession sqlSession, String cacheId) {
    return sqlSession.getConfiguration().getCache(cacheId);
}

private CacheKey getCacheKey(SqlSession sqlSession, String mappingName, Object parameterObject) {
    Configuration configuration = sqlSession.getConfiguration();
    SimpleExecutor executor = new SimpleExecutor(configuration, null);
    MappedStatement mappedStatement = configuration.getMappedStatement(mappingName);
    BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);
    return executor.createCacheKey(mappedStatement, parameterObject, RowBounds.DEFAULT, boundSql);
}

For example:


removeCacheEntry(qlSession, "com.test.MyEntityMapper", "com.test.MyEntityMapper.getById", 1);

Wednesday, 14 May 2014

Installing Ubuntu 14.04 as a guest on a Windows 8.1 VirtualBox host system

Here are three stumbling stones I came accross while installing Ubuntu 14.04 as a guest on a Windows 8.1 VirtualBox host system:

1) To be able to install Ubuntu 14.04 as 64-bit I needed to go to the BIOS settings and enable virtualization

2) After the installation the screen resolution was awfully small and could not be changed. I had to install the "Virtual Guest Additions": sudo apt-get install virtualbox-guest-dkms

3) To be able to access an automatically mounted shared drive you have to add your ubuntu user to the group "vboxsf". Then you will be able to see the shared drive 'sf_*' under '/media', e.g. '/media/sf_mySharedFolder'

Content Security Policy Filter

Hi,

I created a configurable Content Security Policy Java Servlet Filter for setting the 'Content-Security-Policy' / 'Content-Security-Policy-Report-Only' header on a ServletResponse.

It can be found on GitHub: https://github.com/ronaldploeger/ContentSecurityPolicyFilter

Enjoy!

Saturday, 12 April 2014

Java Garbage Collection

I re-read "Java Performance" by Charlie Hunt and here is some general information about garbage collection - mainly for my own reference:

The Java heap size is the size of the young generation and the old generation spaces (does not include the permanent generation) (p.111)

The app memory is the heap size + the perm generation + the threads stack size (p.277)

There are three aspects to garbage collection (p.262)
  • Throughput: How much time is spend in garbage collection vs. how much time is spend on executing application code
  • Latency/Responsiveness: How much pause time in executing application code does GC introduce, i.e. how is the response time affected by GC
  • Memory: The amount of memory used

GC Monitoring

Switch on GC monitoring using: -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:<filename> -> Analyze using GCHisto (p.121)

To shows how long the applicaton runs and how long GC takes add: -XX:+PrintGCApplicationConcurrentTime -XX:+PrintGCApplicationStoppedTime (p.120)


The occupancy of the young generation after a minor GC is the survivor space occupancy (p.111) 

The live data size is the amount of memory of long-lived objects in old and perm generation. It is the size of the heap after a full GC - calculate an average of multiple full GCs (p.113, 268, 274)


The parallel garbage collector is using adative heap sizing, i.e. the HotStop VM initially uses explicit young generation sizing settings (-Xmn, -XX:NewSize, ...) and the automatically adjusts young generation spaces sizes from those settings. This can be disables using the -XX:-UseAdaptiveSizePolicy flag. (p.105 & http://docs.oracle.com/javase/8/docs/technotes/guides/vm/gc-ergonomics.html)

If you wanted to know what GC ergonomics was thinking, try adding -XX:+PrintAdaptiveSizePolicy or -XX:AdaptiveSizePolicyOutputInterval=1. The later will print out information every i-th GC about what the GC ergonomics to trying to do. (https://blogs.oracle.com/jonthecollector/entry/the_unspoken_the_why_of)


Heap size starting points (p.276)
  • Set -Xms & -Xmx to 3 to 4 times the live data size of the old generation
  • Set -XX:PermSize and -XX:MaxPermSize to 1.2 to 1.5 times the live data size of the perm generation
  • The young generation should be 1 to 1.5 times the live data size of the old generation
  • The old generation should be 2 to 3 times the live data size of the old generation

If young GC is takes too long reduce young generation size - if it occures too frequently increase it (p.280)

A parallel (throughput) garbage collector overhead of near 1% is considered well tuned. With >3% overhead tuning may improve the applications performance. It should be less than 5%. The larger the heap the better the opporunity for lower gc overhead - but this will also increase the max. stop-the-world time. p. 122/314

If worst case full GC time is unacceptable switch to a concurrent GC (Concurrent Mark Sweep or G1) (p.287)

Thursday, 10 April 2014

Samaxes Minify Maven Plugin & Eclipse - Deployment to Tomcat

I started using the Samaxes Minify Maven Plugin to minify my JavaScript and CSS files.The usage is pretty easy and I ended up with the following config in my POM


<plugin>
 <groupId>com.samaxes.maven</groupId>
 <artifactId>minify-maven-plugin</artifactId>
 <version>1.7.2</version>
 <executions>
  <execution>
   <id>default-minify</id>
   <phase>generate-resources</phase>
   <configuration>
    <charset>UTF-8</charset>
    <cssSourceDir>css</cssSourceDir>
    <cssSourceFiles>
     <cssSourceFile>x.css</cssSourceFile>
     <cssSourceFile>y.css</cssSourceFile>
     <cssSourceFile>z.css</cssSourceFile>
    </cssSourceFiles>
    <cssFinalFile>style.css</cssFinalFile>
    <jsSourceDir>js</jsSourceDir>
    <jsSourceFiles>
     <jsSourceFile>x.js</jsSourceFile>
     <jsSourceFile>y.js</jsSourceFile>
     <jsSourceFile>z.js</jsSourceFile>
    </jsSourceFiles>
    <jsFinalFile>script.js</jsFinalFile>
    <jsEngine>CLOSURE</jsEngine>
    <webappTargetDir>${basedir}/src/main/webapp</webappTargetDir>
   </configuration>
   <goals>
    <goal>minify</goal>
   </goals>
  </execution>
 </executions>
</plugin>

This worked fine when I ran 'mvn clean install' from my command line.

But I am also using Eclipse (with the whole ecosystem of  m2e / WTP / m2e-wtp) and Tomcat from within Eclipse. And I wanted to be able to publish the generated resources "script-min.js" and "style-min.css" to Tomcat using Eclipse.

Here is what I did in the end:

Did you notice the line in the plugin configuration.


<webappTargetDir>${basedir}/src/main/webapp</webappTargetDir>


By default the Minify Maven Plugin generates the resource into the 'target' folder. By setting this parameter I let the plugin generate the resources into the same folder as the source js and css files.

Now one simply has to run 'mvn generate-resources' either from the command line or from within Eclipse and then do a "Refresh" (F5) on the project and afterwards call 'Publish' on the Tomcat from within Eclipse. If Tomcat is already running it will even auto-publish the change.

This is it and this is what I do.

Note 1:

As an alternative to running 'mvn generate-resources' one can also call "Clean" on the project and let m2e rebuild it. There is just one additional thing if one want to go with this alternative: By default m2e does not execute the "Minify Maven Plugin" so you have to tell it to do so in your pom.xml:


<pluginManagement>
 <plugins>
  <plugin>
   <groupId>org.eclipse.m2e</groupId>
   <artifactId>lifecycle-mapping</artifactId>
   <version>1.0.0</version>
   <configuration>
    <lifecycleMappingMetadata>
     <pluginExecutions>
      <pluginExecution>
       <!-- We need to add this so that m2e (maven2eclipse) will execute the minify-maven-plugin's goal 'minify' when it builds the eclipse project -->
       <pluginExecutionFilter>
        <groupId>com.samaxes.maven</groupId>
        <artifactId>minify-maven-plugin</artifactId>
        <versionRange>[1.0.0,)</versionRange>
        <goals>
         <goal>minify</goal>
        </goals>
       </pluginExecutionFilter>
       <action>
        <execute />
       </action>
      </pluginExecution>
     </pluginExecutions>
    </lifecycleMappingMetadata>
   </configuration>
  </plugin>
 </plugins>
</pluginManagement>

That's it.

Note 2: Within the 'm2e lifecyce mapping' configuration I also tried to set


<execute>
 <runOnIncremental≶true</runOnIncremental>
</execute>

which would generate "script-min.js" and "style-min.css" each time one made a change to any of the source js or css files. This worked nicely when I manually called 'Publish' but I encountered a problem when Tomat was running and trying to auto-publish the changes:

When I changed one of the JS/CSS files Eclipse would get into an endless loop of automatically republishing and building the project.

As I do not very often change the JS/CSS files in this project I decided it was best to go with the manual steps of running 'mvn generate-resources' (from Eclipse), refreshing by hitting F5, and then publishing.

Monday, 7 April 2014

Oracle HotSpot JVM Command Line Flags

Find information about all the Oracle HotSpot JVM Command Line Flags:

One can use -XX:+PrintCommandLineFlags to see the default command line flags. For example


C:\>java -XX:+PrintCommandLineFlags -version

-XX:InitialHeapSize=263467392 -XX:MaxHeapSize=4215478272 -XX:+PrintCommandLineFlags 
-XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation 
-XX:+UseParallelGC
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)

tells us that Java 8 uses the Parallell Garbage Collector as a default (-XX:+UseParallelGC) garbage collector, that the default min heap size is 1/64 (263467392 bytes - about 250MB) of my machines RAM (16GB) and the default max heap size is 25% (4215478272 bytes - about 4 GB), of my machines RAM.

One can also find out the value of a specific command line flag using the tool jinfo. For example


C:\>jinfo -flag MaxHeapSize 3216

-XX:MaxHeapSize=4217372672

tells us again the value of the max heap size. 3216 is the process id of the Java process you are interested in. You can find out the process ids of locally running Java processes using the tool jps


C:\>jps

3216 Bootstrap
5872 Jps
2944 org.eclipse.equinox.launcher_1.3.0.v20130327-1440.jar