#!/bin/sh
## ffdecsa tests for sc
## parameters :
##   --sc-dir=/directory/to/sc/ (default = /usr/local/src/VDR/PLUGINS/src/sc)
## --optimize=yes or long (default=yes)
## --cxx= (default = g++)

#check whether option is supported by this cpu
check_cpu(){
    ok=0
    grep "^flags.* $1 " /proc/cpuinfo >/dev/null 2>&1
    if test $? -eq 0; then
      ok=1
    else
      grep "^flags.* $1\$" /proc/cpuinfo >/dev/null 2>&1
      if test $? -eq 0; then
        ok=1
      fi
    fi
    eval test $ok -eq 1
}

#try to figure out best FFdecsa compiler options
get_cpu_optimization() {
   FLAGS="-Wall -fPIC -g -O3 -fexpensive-optimizations -funroll-loops -fomit-frame-pointer"
   arch=`uname -m`
   processors_flags=`cat /proc/cpuinfo | grep "flags" | head -n 1`
   vendor=`cat /proc/cpuinfo |grep "vendor_id" | head -n 1 | sed -e "s/.*:\W*//"`
   gcc_ver=`$CXX -v 2>&1 | grep "gcc version" | head -n 1`
   gcc_major=`echo $gcc_ver | sed -e 's/^gcc version \([0-9]*\)\..*/\1/'`
   gcc_minor=`echo $gcc_ver | sed -e 's/^gcc version [0-9]*\.\([0-9]*\).*/\1/'`
   if test $gcc_major -gt 4; then
     ARCH="native"
   elif test $gcc_major -eq 4 && test $gcc_minor -ge 2; then
     ARCH="native"
   elif test "x$arch" = "xx86_64"; then
     if test "x$vendor" = "xAuthenticAMD"; then
        ARCH="k8"
     elif test "x$vendor" = "xGenuineIntel"; then
        ARCH="nocona"
     else
        echo **WARNING** - Unknown vendor $vendor - assuming nocona
        ARCH="nocona"
     fi
     FLAGS="$FLAGS -finline-limit=6000000 --param max-unrolled-insns=500"
   elif test "x$arch" = "xathlon-xp"; then
     ARCH="athlon-xp"
     FLAGS="$FLAGS -finline-limit=6000000 --param max-unrolled-insns=500"
   else
     ARCH="pentium"
   fi
   OPTS=""
   for opt in mmx sse sse2; do
     if check_cpu $opt; then
       OPTS="$OPTS $opt"
       FLAGS="$FLAGS -m$opt"
     fi
   done
   CSAFLAGS="$FLAGS -march=$ARCH"
   echo "Processor capabilities: $ARCH ($OPTS )"
}
ffdecsa_opt="yes"
for opt do
  optval="${opt#*=}"
  case "$opt" in
  --cxx=*) CXX="$optval"
  ;;
  --optimize=*) ffdecsa_opt="$optval"
  ;;
  --sc-dir=*) sc_path=`eval echo $optval`
  ;;
  *)
  echo "option $opt unknown"
  exit 1
  ;;
  esac
done

if test "x$sc_path" = "x"; then
        sc_path="/usr/local/src/VDR/PLUGINS/src/sc"
fi

if test "x$CXX" = "x"; then
  CXX=g++
fi
echo "Using C++ compiler: $CXX"

if test "x$ffdecsa_opt" = "xlong"; then
  FFDECSA_MODES="PARALLEL_32_INT PARALLEL_32_4CHAR PARALLEL_32_4CHARA \
                 PARALLEL_64_8CHAR PARALLEL_64_8CHARA PARALLEL_64_2INT \
                 PARALLEL_64_LONG PARALLEL_64_MMX PARALLEL_128_16CHAR \
                 PARALLEL_128_16CHARA PARALLEL_128_4INT PARALLEL_128_2LONG \
                 PARALLEL_128_2MMX PARALLEL_128_SSE PARALLEL_128_SSE2"
elif test "x$ffdecsa_opt" = "xyes"; then
  FFDECSA_MODES="PARALLEL_32_INT PARALLEL_64_2INT PARALLEL_64_LONG \
                 PARALLEL_64_MMX PARALLEL_128_2LONG PARALLEL_128_2MMX \
                 PARALLEL_128_SSE PARALLEL_128_SSE2"
elif test "x$ffdecsa_opt" != "xno"; then
  echo "Bad option to --optimize '$ffdecsa_opt'.  Should be 'yes, no, long'"
  exit 1
fi
if test "x${TMPDIR}" = "x"; then
  TMPDIR="/tmp"
fi


TMPDIR="${TMPDIR}/sc-$$"
mkdir ${TMPDIR}

#Test FFDECSA compile
MAX_MODE=PARALLEL_32_INT
MAX_val=0
if test "x$ffdecsa_opt" != "xno"; then
   if test -f /proc/cpuinfo; then
     get_cpu_optimization
   fi
   TMPOUT="${TMPDIR}/FFdecsa/out"
   mkdir "${TMPDIR}/FFdecsa"
   cp $sc_path/FFdecsa/*.c $sc_path/FFdecsa/*.h $sc_path/FFdecsa/Makefile "${TMPDIR}/FFdecsa/"
   echo "Trying various FFdecsa optimizations..."
#   FLAGS="FLAGS=${CSAFLAGS}"
   for var in ${FFDECSA_MODES}; do
     make -C "${TMPDIR}/FFdecsa" FFdecsa_test "PARALLEL_MODE=${var}" "FLAGS=${FLAGS}" "COMPILER=$CXX"
#     make -C "${TMPDIR}/FFdecsa" FFdecsa_test "PARALLEL_MODE=${var}" "${FLAGS}" "COMPILER=$CXX" >/dev/null 2>&1
     if test $? -ne 0 ; then
       echo "    ${var}: build failed"
     else
       rm -f ${TMPOUT}
       sync;sleep 2; "${TMPDIR}/FFdecsa/FFdecsa_test" > /dev/null 2>"${TMPOUT}"
       if test $? -ne 0; then
         echo "    ${var}: test failed"
       else
         grep FAILED "${TMPOUT}" >/dev/null 2>&1
         if test $? -ne 1; then
           echo "    ${var}: test failed"
         else
           res=`grep "speed=.*Mbit" "${TMPOUT}" | sed -e 's/^.*=\([0-9]*\)\.[0-9]* Mbit.*$/\1/'`
           echo "    ${var}: $res"
           if test $res -gt $MAX_val; then
             MAX_val=$res
             MAX_MODE=$var
           fi
         fi
       fi
     fi
     make -C "${TMPDIR}/FFdecsa" clean >/dev/null 2>&1
   done
   echo "best guess = ${MAX_MODE}"
   echo "save Makefile of sc in $sc_path/Makefile.sv"
   cp $sc_path/Makefile $sc_path/Makefile.sv
   echo "writing FFdecsa compile options to $sc_path/Makefile"
   sed -i 's/^CPUOPT.*/CPUOPT     ?= '${ARCH}'/' $sc_path/Makefile
   sed -i 's/^PARALLEL.*/PARALLEL   ?= '${MAX_MODE}'/' $sc_path/Makefile
   sed -i "s/^CSAFLAGS.*/CSAFLAGS   ?= ${FLAGS}/" $sc_path/Makefile
fi
rm -rf "${TMPDIR}"
