buildcompiler-errorsffmpegosx-lionphash

How to build pHash on MacOSX Lion (using latest ffmpeg-devel)


Building pHash 0.9.4 on OSX can turn out to be tricky. For those of you who've run into issues, my somewhat lengthy answer below might help.


Solution


  • Make sure you've got macports fully updated and working. This means a recent Xcode, and inside Xcode preferences->downloads->components install Command-Line Tools !

    $ sudo port selfupdate
    
    # if you've had previous build issues:
    $ sudo port clean --all
    
    # get pHash
    wget http://www.phash.org/releases/pHash-0.9.4.tar.gz
    tar zxvf pHash-0.9.4.tar.gz
    cd pHash-0.9.4
    
    # remove old versions of ffmpeg, e.g.
    $ sudo port installed ffmpeg
    $ sudo port uninstall --follow-dependents ffmpeg @0.7.11_1+mmx
    $ sudo port uninstall --follow-dependents ffmpeg @0.7.8_0
    
    # install latest ffmpeg-devel version (@20120329 for me) - enable the non-free stuff as well
    $ sudo port install ffmpeg-devel +nonfree
    
    # double check that you have some new header files
    $ ll -tr /opt/local/include/
    
    total 8816
    -rw-r--r--    1 root  admin      191 Dec 23  2004 lua.hpp
    -rw-r--r--    1 root  admin     1026 Dec 27  2007 lualib.h
    -rw-r--r--    1 root  admin     5777 Dec 27  2007 lauxlib.h
    ...
    
    drwxr-xr-x    6 root  admin      204 Jul 12 17:27 libmodplug
    drwxr-xr-x    3 root  admin      102 Jul 12 17:32 libswscale
    drwxr-xr-x    3 root  admin      102 Jul 12 17:32 libswresample
    drwxr-xr-x    3 root  admin      102 Jul 12 17:32 libpostproc
    drwxr-xr-x   41 root  admin     1394 Jul 12 17:32 libavutil
    drwxr-xr-x    5 root  admin      170 Jul 12 17:32 libavformat
    drwxr-xr-x    8 root  admin      272 Jul 12 17:32 libavfilter
    drwxr-xr-x    3 root  admin      102 Jul 12 17:32 libavdevice
    drwxr-xr-x   10 root  admin      340 Jul 12 17:32 libavcodec
    
    # get CImg and copy CImg.h into your pHash dir
    $ cd ..
    $ wget http://downloads.sourceforge.net/project/cimg/CImg-1.5.0.zip
    $ unzip CImg-1.5.0.zip
    $ cp CImg-1.5.0/CImg.h pHash-0.9.4/
    $ cd pHash-0.9.4
    
    # copy the JNI headers from your Java SDK into your pHash dir - for 1.7.0 they're here:
    $ cp /Library/Java//JavaVirtualMachines/1.7.0.jdk/Contents/Home/include/jni.h ./
    $ cp /Library/Java//JavaVirtualMachines/1.7.0.jdk/Contents/Home/include/darwin/jni_md.h ./
    
    # install libsndfile, libsamplerate and mpg123 if not installed already
    $ sudo port install libsndfile
    $ sudo port install libsamplerate
    $ sudo port install mpg123
    
    # now run configure, with Java enabled as you likely want those cool bindings, and expect the missing libavcodec error:
    $ ./configure --enable-java 
    


    OR this which would make more sense:

    $ ./configure --enable-java CPPFLAGS="-I/opt/local/include" LDFLAGS="-L/opt/local/lib" 
    


    but configure completely ignores the new include/lib paths stated :( Seemingly as they're hardcoded inside configure.

    ...
    checking CImg.h usability... no
    checking CImg.h presence... no
    checking for CImg.h... no
    checking whether CImg.h is in the current or src directory.... yes
    
    *** Configuring video Hash ***
    
    checking whether FFmpeg is present... checking for avcodec_alloc_frame in -lavcodec... no
    configure: error: 
    
    *** libavcodec not found.
    



    So then since configure expects all the libs and includes to be in /usr/local/ (not /opt/local) and I cant't get it to look elsewhere, the only thing left to do is brute-force it ! :D

    # edit ./configure as follows
    $ nano configure
    CTRL-W -> search for ' -L/' (note the space)
    
    # edit the lines as follows
    LDFLAGS="$LDFLAGS -L/usr/local/lib -L/opt/local/lib"
    CPPFLAGS="$CPPFLAGS -I/usr/local/include -I/opt/local/include"  
    
    # Or do the newbie version (I actually did this the first time!)
    $ sudo mv /usr/local/lib /usr/local/lib-foo
    $ sudo mv /usr/local/include/ /usr/local/include-foo
    $ sudo ln -s /opt/local/lib /usr/local/lib
    $ sudo ln -s /opt/local/include /usr/local/include
    
    $ ll /usr/local/
    
    total 16
    drwxr-xr-x  32 root  wheel  1088 Jun 29 18:04 bin
    drwxr-xr-x   3 root  wheel   102 Mar  6 14:40 etc
    lrwxr-xr-x   1 root  wheel    18 Jul 12 19:27 include -> /opt/local/include
    drwxr-xr-x  11 root  wheel   374 Jul 12 19:22 include-foo
    lrwxr-xr-x   1 root  wheel    14 Jul 12 19:27 lib -> /opt/local/lib
    drwxr-xr-x  25 root  wheel   850 Jul 12 19:23 lib-foo
    drwxr-xr-x   8 root  wheel   272 Oct 11  2010 sbin
    drwxr-xr-x   4 root  wheel   136 Jun 12 11:52 share
    
    # at this point ./configure should work ok
    


    Time to run make - you'll get a bunch of errors:

    $ make
    
    # on to the code bits:
    # we need to adjust src/cimgffmpeg.cpp to support the latest version of ffmpeg
    # a few things have moved from being deprecated to having been completely changed:
    
    $ make 2>&1 | grep error
    
    cimgffmpeg.cpp:57: error: 'av_open_input_file' was not declared in this scope
    cimgffmpeg.cpp:70: error: 'CODEC_TYPE_VIDEO' was not declared in this scope
    cimgffmpeg.cpp:134: error: 'avcodec_decode_video' was not declared in this scope
    cimgffmpeg.cpp:202: error: 'av_open_input_file' was not declared in this scope
    cimgffmpeg.cpp:216: error: 'CODEC_TYPE_VIDEO' was not declared in this scope
    cimgffmpeg.cpp:283: error: 'avcodec_decode_video' was not declared in this scope
    cimgffmpeg.cpp:339: error: 'av_open_input_file' was not declared in this scope
    cimgffmpeg.cpp:357: error: 'av_open_input_file' was not declared in this scope
    cimgffmpeg.cpp:368: error: 'CODEC_TYPE_VIDEO' was not declared in this scope
    cimgffmpeg.cpp:399: error: 'av_open_input_file' was not declared in this scope
    cimgffmpeg.cpp:410: error: 'CODEC_TYPE_VIDEO' was not declared in this scope
    
    # change as follows; left: original downloaded source, right: modified source 
    
    $ diff ~/Downloads/pHash-0.9.4-fresh/src/cimgffmpeg.cpp ~/dev/pHash-0.9.4/src/cimgffmpeg.cpp
    
    57c57
    <       if(av_open_input_file(&st_info->pFormatCtx, st_info->filename, NULL, 0, NULL)!=0)
    ---
    >       if(avformat_open_input(&st_info->pFormatCtx, st_info->filename, NULL, NULL)!=0)
    
    70c70
    <       if(st_info->pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) 
    ---
    >       if(st_info->pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) 
    
    134c134
    <         avcodec_decode_video(st_info->pCodecCtx, pFrame, &frameFinished,packet.data, packet.size);
    ---
    >         avcodec_decode_video2(st_info->pCodecCtx, pFrame, &frameFinished, &packet);
    
    202c202
    <       if(av_open_input_file(&(st_info->pFormatCtx),st_info->filename,NULL,0,NULL)!=0){
    ---
    >       if(avformat_open_input(&(st_info->pFormatCtx),st_info->filename,NULL,NULL)!=0){
    
    216c216
    <           if(st_info->pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) 
    ---
    >           if(st_info->pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) 
    
    282,283c282
    <           avcodec_decode_video(st_info->pCodecCtx, pFrame, &frameFinished,
    <                                packet.data,packet.size);
    ---
    >           avcodec_decode_video2(st_info->pCodecCtx, pFrame, &frameFinished, &packet);
    
    339c338
    <   if (av_open_input_file(&pFormatCtx, file, NULL, 0, NULL))
    ---
    >   if (avformat_open_input(&pFormatCtx, file, NULL, NULL))
    
    357c356
    <   if (av_open_input_file(&pFormatCtx, file, NULL, 0, NULL))
    ---
    >   if (avformat_open_input(&pFormatCtx, file, NULL, NULL))
    
    368c367
    <        if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) 
    ---
    >        if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) 
    
    399c398
    <   if (av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL))
    ---
    >   if (avformat_open_input(&pFormatCtx, filename, NULL, NULL))
    
    410c409
    <            if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) 
    ---
    >            if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) 
    


    That was tons of fun I'm sure, no worries we're almost there.

    # make should now complete with only useless warnings
    $ make
    $ sudo make -n install
    
    # if all went well you've not got pHash with Java bindings
    # let's build the Java files and test it
    
    $ cd ll bindings/java/org/phash/
    $ javac *.java
    
    # go back to the Java bindins root and run
    $ cd ../..
    
    # oh yeah.. if you actually DID rename the include/lib dirs previously then: 
    $ sudo rm /usr/local/lib
    $ sudo rm /usr/local/include
    $ sudo mv /usr/local/include-foo/ /usr/local/include
    $ sudo mv /usr/local/lib-foo/ /usr/local/lib
    
    # drum roll..
    $ java -Djava.library.path=/usr/local/lib org/phash/pHash -mh ~/Downloads/s01.jpg ~/Downloads/s02.jpg 
    File 1: /Users/xxx/Downloads/s01.jpg
    File 2: /Users/xxx/Downloads/s02.jpg
    0.3159722222222222
    
    # now go try out your image recognition app ideas ;)