Followup questions:

1. Do we want to co-develop this with Carson?
2. Should we throw out QT from the WonderServer?
3. How does the few threads (capture & io) approach sound (using asynchronous socketio)?


A group of us are reworking/rewriting the wonder server so that it will a) serve old video files, b) use TiVo controls on old video (and possibly live feed), c) save annotations to the Berkeley DB (and serve them, too, of course). We didn't find a lot of documentation on the server, so we don't have any stunningly brilliant questions to ask so far. If you can pitch in with any helpful hints/documentation as you have time, that would be great. Thanks! – Daniel Miller

Carson's Response

Well, first, let me just say upfront that I don't consider it a wise use of your time to try to “fix” the existing code. The concept of having a central server that acquires video and telemetry makes sense – and it is clearly what is needed. However, the best thing the wonderserver has to offer is the concept, not the code. My advice: start over. Its important to iterate.

I did have tivo scrubbing working at one point, however there are some fundamental flaws with the wonderserver that preclude effective use in that manner. Here's a breakdown of the problems:

- The database; berkeley db is a good database, but it does not do so well with multithreaded performance. - The messaging format; Using xml was a good concept, but in practice is causes huge performance problems - and these are MOST pronounced during tivo operation. The problem is that parsing is actually really slow. - The complexity. Using QT seems like a good idea, but to be honest, it adds a totally unnecessary learning curve and has some really quirky behavior, especially when it comes to threading and sockets.

That said, let me just highlight the parts of the wonderserver you MAY want to use:

- Huffyuv - I use this to lossless encode frames of video.  I snagged the code from the huffyuv library.
- The capture code; this uses a library referred to in the OpenCV site.  Direct capture will let you get the most flexibility out of capturing.
(note that the two parts i recommend on keeping are things I did NOT write!)

If I may also humbly suggest some solutions to the problems I posed above; these are things I am using in my new version of the server:

- Use asynchronous socketio - this sounds complicated, but leads to MUCH MUCH simpler, lighter code. Google the C10K problem. - Use Google Protocol Buffers for the message format. These are SO SIMPLE and SO FAST. Google uses them. I could talk to you for a while about these, as they use them extensively at my work. To me its a no brainer to use these; use them for network and disk formats. Even if you want an xml-compatability layer, still use them internally if possible.

- Use SQLite instead of berkley db.  Its much faster, much more stable, cleaner (doesnt dump 100 files into your db directory), etc. Google also uses this on Android.
- Stick to posix-style programming.  You dont need ANY qt in the wonderserver core.  You don't need any windows-specific code, except for the capture (if you use direct show capture).

Here's some things I learned:

- It is important to recycle image references.  At one point, for each frame i got from the capture card i would figure out the compressed size, allocate a chunk of memory, and copy it in.  Believe it or not, with four channels of video, this produced pretty bad fragmentation, such that i would get out of memory errors even when i had tons of free memory.  The solution was to allocate fixed-chunk memory references and then recycle them.  You can do this using shared pointers with a custom deleter. Check the WonderImageFactory code for an example of how this is done with qt's QSharedPointers.  I recomend using tr1 shared pointers, or boost shared pointers, both of which are supported by almost all compilers.
- Be careful when trying to compress real-world video.  As Dr, Goodrich will remind you, white-noise is non-compressible.  A huffyuv image can be up to 1.75 as big as the uncompressed image! (i may be off by a decimal point).  Its a good idea to not store an image that is larger than its compressed counterpart!
- Easy on the threads.  One of the reasons for the instability in the wonderserver is its excessive use of threads.  In my mind, you should have one thread for servicing the IO, one thread for capture... and thats about it.  As is, there's a thread for EVERY client, a POOL of threads for encoding images, a thread for the capture, one for the telemtry, and ON AND ON!  You can keep your network link PLENTY busy with a good asynchronous socket engine.  I just wrote one of these at work, so let me know if you want any pointers.
- Buffer your writes - I found that I can get about 80MB/sec performance in the wonderserver.  That is incredibly good for a PC!  To do this, you can't write too often - have an 80MB or so buffer.  Also, it helps to just write to a single file, or to let your file get large before splitting to a new file.

Here's some suggestions that other people gave me that turned out to be BAD IDEAS. Avoid them at all cost:

- "Make sure you don't write the index in a separate file than the images" - The idea here is that, if the index file ever goes away, your image file is useless because you cant determine where your images start and stop.   The problem with this reasoning is that it assumes you will lose your index file.  You are just as likely to lose your index file as your image file.  If you have problems losing files, the solution is simple: create backups!  If you try to keep them together, then you will have to think VERY HARD about a way to quickly access the data.  Better to just use an in-process database like berkley or sqlite.  Truth be told , there is a compromise: Write header information before each image, AND index the file with a DB.  For normal operation, you would use the DB.  For the weirdo who thinks he would prefer to NOT use the db, he can read the images sequentially.
- "Use XML, its flexible" - This is probably OK for the network, but it is INCREDIBLY slow if you are trying to seek through the images on the disk.  Use protocol buffers - its as flexible as xml, and faster (way faster)
- "Use QT - its great!" - QT is great for GUIs.  It is actually a very well done library, but I can't see any reason to use it in the wonderserver core; after all, people only use the wonderserver via the network (or shared memory!). We presently use QT  for threading, sockets, and xml.  You can use pthreads (or pthreads for windows),  or boost to get all the same cross-platform behavior.  Is boost better than qt?  Yes, i think it is better designed.  Again, QT for the gui, posix or boost for the server.

I am working on the new version, and would love to figure out a way to co-develop. I really don't like developing in a vacuum, so if you want to collaborate, let me know! I think we could divide the project up some how - perhaps into a few modules (videocapture, telemetrycapture, logging, network, etc.). If you would rather go ahead down your own branch, i totally understand. Either way, Id love to talk about any questions you have.

Good luck, feel free to ask further questions. Ill be up there about once a month and will swing by to check your progress, i hope.

==Carson

wisar/wonderserver.txt · Last modified: 2014/08/11 19:25 by tmburdge
Back to top
CC Attribution-Share Alike 4.0 International
chimeric.de = chi`s home Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0