FFmpegFrameGrabber maximum video bitrate

1,175 views
Skip to first unread message

Jose Gómez

unread,
Mar 9, 2013, 5:10:01 PM3/9/13
to jav...@googlegroups.com
I am trying to record videos with as high quality as possible. I am mainly using 640x480@60 fps, but also some others, like 320x240@125 fps.

Ideally, I would use uncompressed AVIs, like with Huffyuv to keep the images, but that would require some hardware much more powerful than mine.

On the other hand, H264 encoding is too resource-intensive.

The best solution I have found so far is encoding in MPEG4 with the maximum video bitrate allowed. (If anyone can suggest a better solution, suggestions are welcome)

However, the maximum bitrate changes with the resolution and framerate, so I am changing the calls to recorder.setVideoBitrate() manually. If I try a bitrate too low, I get bad quality. If I try a bitrate too high, I get a message like:

[mpeg4 @ 0x7f55d40f4960] bitrate tolerance too small for bitrate

Is there any way to automatically select or calculate the maximum bitrate that can be set for a certain codec, resolution and framerate?

Otherwise I think I'll just estimate the maximum for a frame at 176x144, and multiply by the increase in size and framerate.


Regards,

Jose.

Samuel Audet

unread,
Mar 10, 2013, 7:52:20 AM3/10/13
to jav...@googlegroups.com
From experience, you won't get much better than Huffyuv or FFV1:
http://compression.ru/video/codec_comparison/lossless_codecs_2007_en.html
Of course, this hasn't been updated since 2007, so there might be better
options available these days...

Anyway, how exactly isn't Huffyuv faster enough? You're unlikely to find
another codec that runs as fast as that with comparable quality and
compression ratio...

If you're interested in lossy compression, don't set the bitrate, simply
set the options to "maximum quality", and the bitrate will end up to
whatever it wants to be.

Samuel

Jose Gómez

unread,
Mar 10, 2013, 12:57:37 PM3/10/13
to jav...@googlegroups.com
From the source at 125 fps, with Huffyuv I manage to record in my system around 80 fps. With MPEG4, I can record around 115 fps. There is some loss of quality, though.

On the other hand, as I only want to record around 10 seconds, I could capture everything to ram, and record to video in a post-processing stage.


> If you're interested in lossy compression, don't set the bitrate, simply set the options to "maximum quality", and the bitrate will end up to whatever it wants to be.

If I don't set any bitrate in FFmpegFrameRecorder, the constructor sets it to 400000, which is too low.

How can I set the maximum quality using FFmpegFrameRecorder?

Samuel Audet

unread,
Mar 11, 2013, 5:13:03 AM3/11/13
to jav...@googlegroups.com
On 03/11/2013 01:57 AM, Jose G�mez wrote:
> If I don't set any bitrate in FFmpegFrameRecorder, the constructor sets
> it to 400000, which is too low.
>
> How can I set the maximum quality using FFmpegFrameRecorder?

Well, it doesn't have an interface for that right now, but check how the
ffmpeg program does it and try to do something similar. It's pretty
codec specific, so I'm not sure how one would go about providing a
generic interface to that...

Samuel

Samuel Audet

unread,
Mar 23, 2013, 10:38:42 PM3/23/13
to jav...@googlegroups.com, Jose Gómez
Hello,
Actually, I've added support for that in this revision:
http://code.google.com/p/javacv/source/detail?r=87516e8715d40c73e9e0e7ea65da70e345aa3498
which relies on a fix in JavaCPP:
http://code.google.com/p/javacpp/source/detail?r=3934c45285d7de75c7c827b3a104cbe89658d6aa

Calling FrameRecorder.setVideoQuality(0) should give you maximum quality
(and implicitly the highest bitrate supported by the codec, which should
give you lossless encoding in the case of x264).

Samuel

Jose Gómez

unread,
Mar 24, 2013, 6:25:30 PM3/24/13
to jav...@googlegroups.com, Jose Gómez
Great! I will try it ASAP. However, I am having trouble compiling JavaCV. After removing some files that were causing missing dependencies (GL*, *CL, ART*, and a few others), this is the error that I currently get:

/home/user/javacv/build/classes/com/googlecode/javacv/cpp/jniopencv_core.cpp: In function ‘_jobject* Java_com_googlecode_javacv_cpp_opencv_1core_cvRedirectError(JNIEnv*, jclass, jobject, jobject, jobject)’:
/home/user/javacv/build/classes/com/googlecode/javacv/cpp/jniopencv_core.cpp:19705:125: error: invalid conversion from ‘char**’ to ‘void**’ [-fpermissive]
In file included from /home/user/javacv/build/classes/com/googlecode/javacv/cpp/opencv_adapters.h:21:0,
                 from /home/user/javacv/build/classes/com/googlecode/javacv/cpp/jniopencv_core.cpp:57:
/usr/local/include/opencv2/core/core_c.h:1760:24: error:   initializing argument 3 of ‘int (* cvRedirectError(CvErrorCallback, void*, void**))(int, const char*, const char*, const char*, int, void*)’ [-fpermissive]
/home/user/javacv/build.xml:30: Java returned: 1
BUILD FAILED (total time: 1 minute 15 seconds)

Any suggestion?

Samuel Audet

unread,
Mar 24, 2013, 11:18:48 PM3/24/13
to jav...@googlegroups.com, Jose Gómez
On 03/25/2013 07:25 AM, Jose G�mez wrote:
> Great! I will try it ASAP. However, I am having trouble compiling
> JavaCV. After removing some files that were causing missing
> dependencies (GL*, *CL, ART*, and a few others), this is the error
> that I currently get:
Or you could build with something like `mvn clean package -Pffmpeg`

> /home/user/javacv/build/classes/com/googlecode/javacv/cpp/jniopencv_core.cpp:
> In function �_jobject*
> Java_com_googlecode_javacv_cpp_opencv_1core_cvRedirectError(JNIEnv*,
> jclass, jobject, jobject, jobject)�:
> /home/user/javacv/build/classes/com/googlecode/javacv/cpp/jniopencv_core.cpp:19705:125:
> error: invalid conversion from �char**� to �void**� [-fpermissive]
> In file included from
> /home/user/javacv/build/classes/com/googlecode/javacv/cpp/opencv_adapters.h:21:0,
> from
> /home/user/javacv/build/classes/com/googlecode/javacv/cpp/jniopencv_core.cpp:57:
> /usr/local/include/opencv2/core/core_c.h:1760:24: error:
> initializing argument 3 of �int (* cvRedirectError(CvErrorCallback,
> void*, void**))(int, const char*, const char*, const char*, int,
> void*)� [-fpermissive]
> /home/user/javacv/build.xml:30: Java returned: 1
> BUILD FAILED (total time: 1 minute 15 seconds)
>
> Any suggestion?
Yeah, it looks like the latest modifications I made to JavaCPP
introduced a couple of compile warnings there. As indicated by GCC, use
the -fpermissive option. Something like this should do the trick: `mvn
clean package -Pffmpeg -Djavacpp.options="-Xcompiler -fpermissive"`

Samuel

Jose Gómez

unread,
Mar 25, 2013, 12:07:59 AM3/25/13
to jav...@googlegroups.com, Jose Gómez
No luck:

/home/user/javacv/target/classes/com/googlecode/javacv/cpp/jniopencv_features2d.cpp:2429:53: error: no matching function for call to ‘cv::BFMatcher::BFMatcher()’
/home/user/javacv/target/classes/com/googlecode/javacv/cpp/jniopencv_features2d.cpp:2429:53: note: candidates are:
In file included from /home/user/javacv/target/classes/com/googlecode/javacv/cpp/jniopencv_features2d.cpp:56:0:
/usr/local/include/opencv2/features2d/features2d.hpp:1201:13: note: cv::BFMatcher::BFMatcher(int, bool)
/usr/local/include/opencv2/features2d/features2d.hpp:1201:13: note:   candidate expects 2 arguments, 0 provided
/usr/local/include/opencv2/features2d/features2d.hpp:1198:20: note: cv::BFMatcher::BFMatcher(const cv::BFMatcher&)
/usr/local/include/opencv2/features2d/features2d.hpp:1198:20: note:   candidate expects 1 argument, 0 provided

Samuel Audet

unread,
Mar 25, 2013, 12:09:07 AM3/25/13
to jav...@googlegroups.com
On 03/25/2013 01:07 PM, Jose G�mez wrote:
> No luck:

Looks like this isn't OpenCV 2.4.4, so try with that version

Jose Gómez

unread,
Mar 25, 2013, 8:58:00 PM3/25/13
to jav...@googlegroups.com
Wow, it works great! I have tried with different resolutions, and the quality is as good as manually tuning the video quality parameter in order to specify the highest video bitrate allowed.

However, with H264, I get an error:

x264 [error]: baseline profile doesn't support lossless

So, in this case (as I don't know how to specify the profile), I am setting the quality to 10 instead of 0.

Thanks a lot! :)


PS: I still can capture at a much higher framerate in MPEG4 (640x480@120 fps) than in any other video format that I have tried, including FLV, MPG and H264.

Samuel Audet

unread,
Mar 26, 2013, 4:22:39 AM3/26/13
to jav...@googlegroups.com
Great :)

According to http://en.wikipedia.org/wiki/H.264/MPEG-4_AVC , only the
highest profile supports lossless, so you could try to call
FrameRecorder.setProfile("high444") to set that for x264. You might need
to call setPixelFormat(AV_PIX_FMT_YUV444P) as well... AV_PIX_FMT_BGR24
or AV_PIX_FMT_RGB24 may work too, never tried any of that though.

Samuel
Reply all
Reply to author
Forward
0 new messages