ffmpeg + MT + SVQ3 video = Argh...

Try decoding a video with SVQ3 video codec with multithreading enabled (e.g. -threads 4) ffmpeg r25526 simply refuses to decode it:

Stream #0.0(eng): Video: svq3, yuvj420p, 640x476, 1732 kb/s, 25 fps, 25 tbr, 600 tbn, 600 tbc
...
[svq3 @ 0x806bfe0] SVQ3 does not support multithreaded decoding, patch welcome! (check latest SVN too)
...
Error while opening decoder for input stream #0.0

Instead of simply just using only one thread and just working ffmpeg bails. What a pain.

You need to specify "-threads 1" or no threads option at all for decoding to work.

Linux HTML Rendering Widgets

When you start a new open source project and decide to provide parts or the whole UI by an HTML widget you face the problem of first finding HTML widget libraries, especially light weight ones, and then using the correct one to avoid throwing away the code at a later point when you find one important feature missing.

With this blog post I try to give a summary of existing open source HTML renderer libraries in the Linux world. I have some background experiences with the libraries from working on Liferea where we started with GtkHTML2, later added GtkMozembed support, then added Webkit support and finally switched to WebKit-only rendering.

The following table tries to summarize the simple availability of the different HTML renderers:

Name Toolkit Platform Derived From Driving Force Active
KHTML QT % KDE KDE Yes
wxHtml wxWidgets GTK, Windows KHTML wxWidgets Yes
GtkHtml GTK+ 1.0 GNOME 1 KHTML GNOME 1 No, long gone
GtkHtml2 GTK+ 2.0 GNOME 2 GtkHtml GNOME 2 No, v2.11: Aug 2007
GtkHtml3 GTK+ 2.0 GNOME 2 GtkHtml Ximian, Evolution No, v3.14: May 2008
GtkMozEmbed GTK+ 2.0 Gecko % Mozilla Somewhat
WebKitGtk GTK+ 2.0
GTK+ 3.0
Webkit KHTML Apple Safari Yes

Note: My summary somewhat complements this Wikipedia list. Still it focusses more on Linux renderers and does correctly distinguish between the rather mad history of GtkHtml*.

Given the list above one could conclude the only acceptable renderers are KTHML, wxHtml and WebkitGtk simply based on project activity. Still other renderers like GtkHtml2 and GtkHtml3 have gone a long way and provide a limited but stable functionality.

But the important question is: What features are supported by the different renderers?



Name Widget
Embed
Full
HTML
CSS JS Java/Flash Editor
KHTML y y 1,2,3 y y n
wxHtml y n none n n n
GtkHtml y y none n n y
GtkHtml2 y y 1,2 inline n n n
GtkHtml3 y y none n n y
GtkMozEmbed n y 1,2,3 y y n
WebKitGtk n y 1,2,3 y y n

The feature matrix along with the platform listing explains why a lot of those old renderer libraries are still around. Given you want to render simple markup in an email client you might still choose wxHtml or GtkHtml3, with the latter one providing you with a HTML editor for rich mail editing. Of course when you want to allow your users to have fully fledged inline browsing you need to use either KTHML, GtkMozEmbed or Webkit. Currently I believe WebKitGtk to be the best choice as it's widget gets a lot of attention, which GtkMozEmbed never had while being unstable and rather limited at the same time.

If you find mistakes or have something to add please post a comment!

Comparison of FLV and MP4 metadata tagging tools (injectors)

This post is a comparison of the performance of different tools available to tag FLV and MP4 containers with specific metadata (e.g. title, keyframes, generator or other custom fields...). For FLV containers flvtool2, flvtool++ and yamdi are compared. For the MP4 container MP4box, AtomicParsley and ffmpeg are compared.

Here are the IMO three most important FLV taggers tested on a 125MB FLV:

Name Duration Large Files In Memory Custom Tags Command
flvtool2 1.0.6 3min 11s no no yes flvtool2 -UP -band:Test -user:Test -date:1995 -genres:pop test.flv
flvtool++ 1.2.1 3s no yes yes flvtool++ test.flv -tag band "Test" -tag user "Test" -tag date "1995" -tag genres "pop" test2.flv
yamdi 1.6 1.5s yes no no
(patch)
yamdi -i test.flv -o test2.flv -c "Test"

The performance of flvtool2 is horrendous. For films of 120min it will take hours to process. Therefore: Do not use it! Use Facebooks flvtool++ instead. I guess the bad performance results from it being built in Ruby. Also notice the "Large File" column indicating large file support which officially only yamdi support (by adding compile flag -D_FILE_OFFSET_BITS=64). Another important point is the "In Memory" column indicating that flvtool++ loads the entire file into memory when tagging, which is problematic when tagging large files. Given this results only yamdi should be used for FLV tagging!

Now for the MP4 tagging. Here you can select between a lot of tools from the net, but only a few of them are command line based and available for Unix. The MP4 test file used is 100MB large.

Name Duration Command
AtomicParsely 0.6s AtomicParsley test.mp4 --artist "Test" --genre "Test" --year "1995"
mp4box 0.6s MP4Box -itags Name=Test:Artist=Me:disk=95/100 test.mp4
ffmpeg 0.6 0.8s ffmpeg -i test.mp4 -metadata title="Test" -metadata artist="Test" -metadata date="1995" -acodec copy -vcodec copy test2.mp4

Given that recent ffmpeg brings the tagging for MP4 out of the box (it doesn't for FLV though) you do not even need an external tool to add the metadata,

Making flvtool++ work with large files

The flvtool++ by Facebook is a fast FLV metadata tagger, but at least up to v1.2.1 it lacks large file support. Here is a simple patch to make it work with large files:

--- flvtool++.orig/fout.h	2009-06-19 05:06:47.000000000 +0200
+++ flvtool++/fout.h	2010-10-12 15:51:37.000000000 +0200
@@ -21,7 +21,7 @@
   void open(const char* fn) {
     if (fp) this->close();
 
-    fp = fopen(fn, "wb");
+    fp = fopen64(fn, "wb");
     if (fp == NULL) {
       char errbuf[256];
       snprintf(errbuf, 255, "Error opening output file \"%s\": %s", fn, strerror(errno));

--- flvtool++.orig/mmfile.h	2009-06-19 05:29:43.000000000 +0200
+++ flvtool++/mmfile.h	2010-10-12 15:46:00.000000000 +0200
@@ -16,7 +16,7 @@
 public:
   mmfile() : fd(-1) {} 
   mmfile(char* fn) {
-    fd = open(fn, O_RDONLY);
+    fd = open(fn, O_RDONLY | O_LARGEFILE);
     if (fd == -1) throw std::runtime_error(string("mmfile: unable to open file ") + string(fn));
     struct stat statbuf;
     fstat(fd, &statbuf);

Note: While this patch helps you to process large files flvtool++ will still load the entire file into memory!!! Given this you might want to use a different injector like yamdi. For a
comparsion of existing tools have a look at the Comparison of FLV and MP4 metadata tagging tools.

flvtool2 1.0.6 Bugs

Crash Variant #1

Sometimes flvtool2 1.0.6 crashes on FLVs created by ffmpeg or mencoder. The FLV video itself is playable without the metadata and looks fine, still flvtool2 crashes like this:


$ flvtool2 -kUP -metadatacreator:'some label' video.flv
ERROR: EOFError
ERROR: /usr/lib/ruby/site_ruby/1.8/flv/amf_string_buffer.rb:37:in `read'
ERROR: /usr/lib/ruby/site_ruby/1.8/flv/amf_string_buffer.rb:243:in `read__STRING'
ERROR: /usr/lib/ruby/site_ruby/1.8/flv/audio_tag.rb:56:in `read_header'
ERROR: /usr/lib/ruby/site_ruby/1.8/flv/audio_tag.rb:47:in `after_initialize'
ERROR: /usr/lib/ruby/site_ruby/1.8/flv/tag.rb:56:in `initialize'
ERROR: /usr/lib/ruby/site_ruby/1.8/flv/stream.rb:447:in `new'
ERROR: /usr/lib/ruby/site_ruby/1.8/flv/stream.rb:447:in `read_tags'
ERROR: /usr/lib/ruby/site_ruby/1.8/flv/stream.rb:58:in `initialize'
ERROR: /usr/lib/ruby/site_ruby/1.8/flvtool2/base.rb:272:in `new'
ERROR: /usr/lib/ruby/site_ruby/1.8/flvtool2/base.rb:272:in `open_stream'
ERROR: /usr/lib/ruby/site_ruby/1.8/flvtool2/base.rb:238:in `process_files'
ERROR: /usr/lib/ruby/site_ruby/1.8/flvtool2/base.rb:225:in `each'
ERROR: /usr/lib/ruby/site_ruby/1.8/flvtool2/base.rb:225:in `process_files'
ERROR: /usr/lib/ruby/site_ruby/1.8/flvtool2/base.rb:44:in `execute!'
ERROR: /usr/lib/ruby/site_ruby/1.8/flvtool2.rb:168:in `execute!'
ERROR: /usr/lib/ruby/site_ruby/1.8/flvtool2.rb:228
ERROR: /usr/bin/flvtool2:2:in `require'
ERROR: /usr/bin/flvtool2:2
$

In the Wowza Media Server support forum is a hint on how to patch flvtool2 to solve the issue:

--- /usr/local/lib/site_ruby/1.8/flv/audio_tag.rb	2009-11-12 10:46:13.000000000 +0100
+++ lib/flv/audio_tag.rb	2010-03-17 11:25:35.000000000 +0100
@@ -44,7 +44,9 @@
     
     def after_initialize(new_object)
       @tag_type = AUDIO
-      read_header
+      if data_size > 0
+      	read_header
+      end
     end
 
     def name

Crash Variant #2

Here is another crashing variant:


$ flvtool2 -kUP -metadatacreator:'some label' video.flv
ERROR: EOFError
ERROR: /usr/local/lib/site_ruby/1.8/flv/amf_string_buffer.rb:37:in `read'
ERROR: /usr/local/lib/site_ruby/1.8/flv/amf_string_buffer.rb:75:in `read__AMF_string'
ERROR: /usr/local/lib/site_ruby/1.8/flv/amf_string_buffer.rb:90:in `read__AMF_mixed_array'
ERROR: /usr/local/lib/site_ruby/1.8/flv/amf_string_buffer.rb:134:in `read__AMF_data'
ERROR: /usr/local/lib/site_ruby/1.8/flv/meta_tag.rb:40:in `after_initialize'
ERROR: /usr/local/lib/site_ruby/1.8/flv/tag.rb:56:in `initialize'
ERROR: /usr/local/lib/site_ruby/1.8/flv/stream.rb:451:in `new'
ERROR: /usr/local/lib/site_ruby/1.8/flv/stream.rb:451:in `read_tags'
ERROR: /usr/local/lib/site_ruby/1.8/flv/stream.rb:58:in `initialize'
ERROR: /usr/local/lib/site_ruby/1.8/flvtool2/base.rb:272:in `new'
ERROR: /usr/local/lib/site_ruby/1.8/flvtool2/base.rb:272:in `open_stream'
ERROR: /usr/local/lib/site_ruby/1.8/flvtool2/base.rb:238:in `process_files'
ERROR: /usr/local/lib/site_ruby/1.8/flvtool2/base.rb:225:in `each'
ERROR: /usr/local/lib/site_ruby/1.8/flvtool2/base.rb:225:in `process_files'
ERROR: /usr/local/lib/site_ruby/1.8/flvtool2/base.rb:44:in `execute!'
ERROR: /usr/local/lib/site_ruby/1.8/flvtool2.rb:168:in `execute!'
ERROR: /usr/local/lib/site_ruby/1.8/flvtool2.rb:228
ERROR: /usr/local/bin/flvtool2:2:in `require'
ERROR: /usr/local/bin/flvtool2:2
$

I have not yet found a solution...

Update: I have found crash variant #2 to often happen with larger files. Using flvtool++ instead of flvtool2 always solved the problem. Using flvtool++ is also a good idea as it is much faster than flvtool2. Still both tools have their problems. More about this in the Comparison of FLV and MP4 metadata tagging tools.

Why decoding AAC with ffmpeg doesn't work...

Update: The workaround for the problem doesn't work for ffmpeg versions more recent than 20.06.2011 as libfaad support was dropped in favour of the now stable native ffmpeg AAC encoder! If you still have a separate compilation of libfaad you can workaround using the "faad" encoder tool as described in this post.

If you are using recent ffmpeg versions to decode a .MOV file you might get the following error:

Stream #0.0(eng): Audio: aac, 48000 Hz, 2 channels, s16
Stream #0.1(eng): Video: h264, yuv420p, 1280x530, PAR 1:1 DAR 128:53, 25 tbr, 25 tbn, 50 tbc
Output #0, flv, to 'test.flv':
Stream #0.0(eng): Video: flv (hq), yuv420p, 400x164 [PAR 101:102 DAR 050:2091], 
q=2-31, 300 kb/s, 1k tbn, 25 tbc
Stream #0.1(eng): Audio: libmp3lame, 22050 Hz, 2 channels, s16, 64 kb/s
Stream mapping:
Stream #0.1 -> #0.0
Stream #0.0 -> #0.1
Press [q] to stop encoding
[aac @ 0x80727a0]channel element 1.0 is not allocated
Error while decoding stream #0.0
Error while decoding stream #0.0
Error while decoding stream #0.0
Error while decoding stream #0.0
Error while decoding stream #0.0
Error while decoding stream #0.0
[...]

The message "Error while decoding stream #0.0" is repeated continuously. The resulting video is either unplayable or has no sound. Still the input video is playable in all standard players (VLC, in Windows...). The reason for the problem as I understood it is that the ffmpeg-builtin AAC codec cannot handle an audio stream stream with index "1.0". This is documented in various bugs (see ffmpeg issues #800, #871, #999, #1733...). It doesn't look like this will be handled by ffmpeg very soon. In fact it could well be that they'll handle it as an invalid input file.

Solution: Upgrade to latest ffmpeg and faad library version and add " -acodec libfaad " in front of the "-i" switch. This uses the libfaad AAC decoder, which is said to be a bit slower than the ffmpeg-builtin, but which decodes the AAC without complaining. For example:

ffmpeg -acodec libfaad -i input.mov -b 300kbit/s -ar 22050 -o test.flv

The "-acodec" preceding the "-i" option only influences the input audio decoding, not the audio encoding.

rsync: buffer_append_space: alloc 10512504 not supported

If an rsync call gives you the following:

buffer_append_space: alloc 10512504 not supported
rsync: writefd_unbuffered failed to write 4092 bytes [sender]: Broken pipe (32)
rsync: connection unexpectedly closed (36 bytes received so far) [sender]
rsync error: unexplained error (code 255) at io.c(635) [sender=3.0.3]

Don't bother to debug rsync! This is an SSH problem. You need to upgrade your SSH version (which is propably some 4.3 or older).

Reasons for ffmpeg "av_interleaved_write_frame(): I/O error occurred"

If you are unlucky you might see the following ffmpeg error message:
Output #0, image2, to 'output.ppm':
Stream #0.0: Video: ppm, rgb24, 144x108, q=2-31, 200 kb/s, 90k tbn, 29.97 tbc
Stream mapping:
Stream #0.0 -> #0.0
Press [q] to stop encoding
av_interleaved_write_frame(): I/O error occurred
Usually that means that input file is truncated and/or corrupted.

The above error message was produced with a command like this
ffmpeg -v 0 -y -i 'input.flv' -ss 00:00:01 -vframes 1 -an -sameq -vcodec ppm -s 140x100 'output.ppm'

There are several possible reasons for the error message "av_interleaved_write_frame(): I/O error occurred".

  1. You are extracting a thumb and forgot to specify to extract a single frame only (-vframes 1)
  2. You have a broken input file.
  3. And finally: The target file cannot be written.

The above was caused by problem three. After a lot of trying I found that the target directory did not exist. Quite confusing.

How to Quickly Set up Squid

Ever needed to test your HTTP client app proxy support? Need an instant proxy test setup?

Here is a fast way to set up a local proxy server on Debian using squid:

1.) # apt-get install squid
2.) Edit the squid configuration /etc/squid/squid.conf
2.) a) Edit ACLs. Ensure to have something like the following:

acl all src all
acl users proxy_auth REQUIRED

2.) b) Edit access definitions. You need (order is important):

http_access allow users
http_access deny all

2.) c) Setup a dummy authentication module

auth_param basic program /usr/local/bin/squid_dummy_auth
auth_param basic children 5
auth_param basic realm Squid proxy-caching web server
auth_param basic credentialsttl 2 hours
auth_param basic casesensitive off

3.) Create a authentication script

# vi /usr/local/bin/squid_dummy_auth

Insert something like:

#!/bin/sh

while read dummy;
do
   echo OK
done

# chmod a+x /usr/local/bin/squid_dummy_auth

4.) Restart squid

# /etc/init.d/squid restart

With this you have a working Basic Auth proxy test setup running on localhost:3128.

1000 Problems When Compiling ffmpeg and mplayer

This is a short compilation of ffmpeg/mplayer compilation pitfalls:

libx264:
If compilation fails with an error about the numbers of parameters in common/cpu.c
you need to check which glibc version is used. Remove the second parameter to
sched_getaffinity() if necessary and recompile.

ffmpeg+x264
ffmpeg configure fails with:

ERROR: libx264 not found
If you think configure made a mistake, make sure you are using the latest
version from SVN.  If the latest version fails, report the problem to the
[email protected] mailing list or IRC #ffmpeg on irc.freenode.net.
Include the log file "config.err" produced by configure as this will help
solving the problem.

This can be caused by two effects:

  • Unintended library is used for linking. Check wether you have different ones installed. Avoid this and uninstall them if possible. If necessary use LD_LIBRARY_PATH or --extra-ldflags to change the search order.
  • Incompatible combination of ffmpeg and libx264. Older libx264 provide a method x264_encoder_open which older ffmpeg versions do check for. More recent libx264 add a version number to the method name. Now when you compile a new libx264 against an older ffmpeg the libx264 detection that relies on the symbol name fails. As a workaround you could hack the configure script to check for "x264_encoder_open_78" instead of "x264_encoder_open" (given that 78 is the libx264 version you use).

ffmpeg+x264
ffmpeg compilation fails on AMD64 with:

libavcodec/svq3.c: In function 'svq3_decode_slice_header':
libavcodec/svq3.c:721: warning: cast discards qualifiers from pointer target type
libavcodec/svq3.c:724: warning: cast discards qualifiers from pointer target type
libavcodec/svq3.c: In function 'svq3_decode_init':
libavcodec/svq3.c:870: warning: dereferencing type-punned pointer will break strict-aliasing rules
/tmp/ccSySbTo.s: Assembler messages:
/tmp/ccSySbTo.s:10644: Error: suffix or operands invalid for `add'
/tmp/ccSySbTo.s:10656: Error: suffix or operands invalid for `add'
/tmp/ccSySbTo.s:12294: Error: suffix or operands invalid for `add'
/tmp/ccSySbTo.s:12306: Error: suffix or operands invalid for `add'
make: *** [libavcodec/h264.o] Error 1

This post explains that this is related to a glibc issue and how to patch it.

ffmpeg+x264
ffmpeg compilation fails with:

libavcodec/libx264.c: In function 'encode_nals':
libavcodec/libx264.c:60: warning: implicit declaration of function 'x264_nal_encode'
libavcodec/libx264.c: In function 'X264_init':
libavcodec/libx264.c:169: error: 'x264_param_t' has no member named 'b_bframe_pyramid'
make: *** [libavcodec/libx264.o] Error 1

This means you are using incompatible ffmpeg and libx264 versions. Try to upgrade ffmpeg or to downgrade libx264.

ffmpeg+video4linux

/usr/include/linux/videodev.h:55: error: syntax error before "ulong"
/usr/include/linux/videodev.h:71: error: syntax error before '}' token

Workaround:

--- configure.ac.080605 2005-06-08 21:56:04.000000000 +1200
+++ configure.ac        2005-06-08 21:56:42.000000000 +1200
@@ -1226,6 +1226,7 @@
 AC_CHECK_HEADERS(linux/videodev.h,,,
 [#ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
+#include <sys/types.h>
 #endif
 #ifdef HAVE_ASM_TYPES_H
 #include <asm/types.h>

http://www.winehq.org/pipermail/wine-devel/2005-June/037400.html

oder Workaround:
--disable-demuxer=v4l --disable-muxer=v4l --disable-demuxer=v4l2 --disable-muxer=v4l2

ffmpeg+old make

make: *** No rule to make target `libavdevice/libavdevice.so', needed by `all'.  Stop.

Problem: GNU make is too old, you need at least v3.81

http://www.mail-archive.com/[email protected]/msg01284.html

make: *** No rule to make target `install-libs', needed by `install'.  Stop.

Problem: GNU make is too old, you need at least v3.81

http://ffmpeg.arrozcru.org/forum/viewtopic.php?f=1&t=833

Mplayer+old make

make: expand.c:489: allocated_variable_append: Assertion `current_variable_set_list->next != 0' failed.

Problem: GNU make is too old, you need at least v3.81

MPlayer

i386/dsputil_mmx.o i386/dsputil_mmx.c
i386/dsputil_mmx.c: In function `transpose4x4':
i386/dsputil_mmx.c:621: error: can't find a register in class `GENERAL_REGS' while reloading `asm'

Workaround: Add the following to your configure call
--extra-cflags="-O3 -fomit-frame-pointer"

Note: if this somehow helped you and you know something to be added feel free to post a comment!

Syndicate content Syndicate content