Sunday, September 9, 2012

libav in C++

libav, which is intended for codecs, also serves as a nice signal processing library for scientific applications as it has assembly FFT routines optimized for various processors including x86 SSE and ARM NEON.  Written in C for C, it can be a little tricky to use in C++.

The first trick is to wrap the #includes within extern "C":

extern "C" {
    #include <libavutil/avutil.h>
    #include <libavcodec/avfft.h>
}


The second trick is that to use the nice C++ array types std::vector or boost::multi_array, it is necessary to use a custom allocator class that calls the libav av_malloc() and av_free().  The reason is that these ensure the 32-byte alignment that libav assumes (without checking every time) is present when it utilizes SIMD instructions.  Without a custom allocator, std::vector and boost::multi_array just use new[], which does not allocate aligned, and libav in the process of ANDing addresses ends up running past the end of the buffer and generating a segmentation fault.

The code below uses a custom allocator adapted from The C++ Standard Library -- a Tutorial and Reference.  The advantage of using std::vector or boost::multi_array, of course, is automated memory management using the Resource Acquisition Is Initialization pattern/idiom, similar to C++ auto_ptr (which can't be used for arrays because it is hard-coded to delete instead of delete[]).  Although std::vector is used below, the same allocator works equally well with boost::multi_array.


#define __STDC_CONSTANT_MACROS

#include <cstring>
#include <vector>

extern "C" {
#include <libavutil/avutil.h>
#include <libavcodec/avfft.h>
}

template <typename T> class allocator_av {
public:
    typedef T               value_type;
    typedef T*              pointer;
    typedef const T*        const_pointer;
    typedef T&              reference;
    typedef const T&        const_reference;
    typedef std::size_t     size_type;

    template <typename U>
    struct rebind {
        typedef allocator_av<U> other;
    };

    allocator_av() {}
    template <typename U> allocator_av(const allocator_av<U>&) {}
    size_type max_size () const { return 1 << 16; }

    pointer allocate (size_type num, const void* = 0) {
        return  static_cast<pointer>(av_malloc(num*sizeof(T)));
    }

    void construct (pointer p, const T& value) {}
    void destroy (pointer p) {}
    void deallocate (pointer p, size_type num) { av_free(p); }
 };

int main(int argc, char** argv) {
    std::vector<FFTComplex, allocator_av<FFTComplex> > z(256);
    FFTContext* c = av_fft_init(8, 0);
    av_fft_permute(c, z.data());
    av_fft_calc(c, z.data());
    av_free(c);
}

Tuesday, August 28, 2012

Samsung 11.8 tablet key for signal processing

The Samsung 11.8, information about which came out of the Apple lawsuit, is a good match for in-the-field scientific/data acquisition/NDT applications.  Why?  Because it will be the first tablet with an ARM Cortex-A15 processor, specifically the Samsung Exynos 5.

It's just an ARM processor, right?  ARM is extremely low power consumption, but mediocre computational performance, right?  Wrong -- ARM has grown up.  ARM has maintained its extreme low power consumption while catching up to Intel performance.  And the Cortex-A15 is a huge step forward in that regard.  It features NEON, which is the ARM equivalent to Intel MMX/SSE/AVX vector processing, which speeds up by multiples the signal and image processing used in scientific computing.  And the NEON in Cortex-A15 can do double-precision.  Oddly, the current generation Samsung Galaxy tablet, 10.1, dropped NEON even though its even older predecessor had it.  But the Samsung 11.8 Cortex-A15 NEON has 128-bit ALUs instead of the 64-bit ALUs that the earlier ARM NEON processors had.

The Samsung 10.1 has thus far escaped injunction from Apple, so there is hope the 11.8 will as well.  The iPad won't get Cortex-A15 until the iPad 5.  There is hope that the Samsung 11.8 will be unveiled tomorrow at the Unpacked event in Berlin.

Monday, August 27, 2012

C++ regex source string cannot be a temporary

regex is new to C++11 and was available via Boost before then.  In playing around with it, I could not figure out why the following worked sometimes, but not all the time:

// Bad code
smatch sm1;
regex_search(string("helloworld.jpg"), sm1,

             regex("(.*)jpg"));
cout << sm1[1] << endl;


Then, thanks to stackoverflow.com I learned that smatch retains just pointers to the source string "helloworld.jpg" and not actual substrings.  So when the temporary object string("helloworld.jpg") gets released, the smatch pointers are left pointing to released (and thus undefined) memory.

The correct code is:

// Good code
smatch sm1;
string s1("helloworld.jpg")
regex_search(s1, sm1, regex("(.*)jpg"));
cout << sm1[1] << endl;


Now, in real code you wouldn't pass a hard-coded temporary object, but during debug/development you might to test out how regex handles different scenarios, which is what I was trying to do when I ran into this.

Thursday, June 21, 2012

W7 can finally rotate bitmap fonts

With HTML5 canvas and its built-in ability to rotate text, I came across (i.e. learned the hard way) about the limitations of bitmap fonts, such as MS Sans Serif, in XP.  XP has trouble rotating bitmap fonts at small point sizes, while Windows 7 does not.  So the following HTML5 canvas code works in Windows 7 & Firefox but fails under XP & Firefox:
<html>
 <head>
  <script type="text/javascript">
   window.onload = function() {
    var ctx = document.getElementById('canvas').getContext('2d');
    ctx.translate(100,100);
    ctx.font = "9px MS Sans Serif";
    ctx.rotate(-Math.PI/2);
    ctx.fillText("TEST", 10, 10);
   }
  </script>
 </head>
 <body>
  <canvas id="canvas" width=800 height=500 />
 </body>
</html>
Switching to a TrueType font such as Arial solves the problem.  So the lesson is to avoid bitmap fonts such as MS Sans Serif when using HTML5 Canvas.

This change in font handling for Windows 7 is probably related to Microsoft's revamping of font scaling to deal with high-resolution netbooks with tiny screens.

Sunday, June 17, 2012

HTML5 is the holy grail

I was initially excited about the UI design philosophy of Win8 Metro. But then I realized that HTML5 can do 95% of what Metro can, and also be truly cross-platform.

I see HTML5 as the cross-platform holy grail that developers have been seeking since the WORA days of Java 15 years ago. First it was supposed to be Java, then Microsoft embraced and extinguished it, and besides it had too big of a footprint download (and a clumsy download process to boot). Then Flash was supposed to be the universal small-footprint. It was just about to take off, then Apple extinguished it by not supporting it at all (completely skipping the "embracing" step). Then Microsoft finally decided to stop holding back .NET from web development -- the purpose for which it seemingly was originally designed but never delivered upon until Silverlight. But by then Windows market share was too small for Microsoft to force a Windows-only solution on the web world.

Even when it comes to CPU-intensive signal & image processing, Javascript seems to be "fast enough".  E.g. these guys show real-time 2-D FFT. Admittedly, the combination of SSE/AVX and multi-threading/multi-core would have provided a 30x speedup, but I've been playing around with real-time 2D graphics in JavaScript and have been amazed at its performance. I was even guilty of premature optimization -- I started out coding for double-buffering the graphics with two Canvases and ended up throwing out the double-buffering because with just one Canvas there was no flicker.

On today's processors, Javascript will be "fast enough" for many applications. E.g., I do scientific software for a living, and I'm partitioning the work into what has to be done natively -- mostly the acquisition and crunching of tens of gigabytes of data at a time -- vs. what can be done cross-platform -- the final post-processing of tens of megabytes of pre-processed data.

Javascript can even access hardware-accelerated 3D with WebGL.

HTML5 is W3C standard. It's not Sun. It's not Adobe. It's not Microsoft. It's W3C.

HTML5 is the holy grail of WORA.

Wednesday, February 22, 2012

ProgramData virtualization

It's not enough to move data stores from Program Files to ProgramData when upgrading applications from XP to Vista/W7. It's also necessary to, in the application installation, set the permissions on those files to read/write for the group "Users". Otherwise, Vista/W7 will silently virtualize those files into shadow copies to the Users folder on a per-user basis.

Thursday, June 9, 2011

2GB should be more than enough for anyone

Turns out Win32 won't create new threads under low memory conditions. Oh, seems obvious in hindsight -- but I didn't realize I was hitting the 2GB barrier.

Now, if only the hardware vendors -- namely for the A/D data acquisition boards I use -- would support 64-bit Windows...