Index: pjproject/trunk/aconfigure
===================================================================
--- pjproject/trunk/aconfigure	(revision 4814)
+++ pjproject/trunk/aconfigure	(revision 4815)
@@ -1,8 +1,10 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for pjproject 2.x.
+# Generated by GNU Autoconf 2.68 for pjproject 2.x.
 #
 #
-# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+# Foundation, Inc.
 #
 #
@@ -133,29 +135,4 @@
 (unset CDPATH) >/dev/null 2>&1 && unset CDPATH
 
-# Use a proper internal environment variable to ensure we don't fall
-  # into an infinite loop, continuously re-executing ourselves.
-  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
-    _as_can_reexec=no; export _as_can_reexec;
-    # We cannot yet assume a decent shell, so we have to provide a
-# neutralization value for shells without unset; and this also
-# works around shells that cannot unset nonexistent variables.
-# Preserve -v and -x to the replacement shell.
-BASH_ENV=/dev/null
-ENV=/dev/null
-(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
-case $- in # ((((
-  *v*x* | *x*v* ) as_opts=-vx ;;
-  *v* ) as_opts=-v ;;
-  *x* ) as_opts=-x ;;
-  * ) as_opts= ;;
-esac
-exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
-# Admittedly, this is quite paranoid, since all the known shells bail
-# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-as_fn_exit 255
-  fi
-  # We don't want this to propagate to other subprocesses.
-          { _as_can_reexec=; unset _as_can_reexec;}
 if test "x$CONFIG_SHELL" = x; then
   as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
@@ -191,6 +168,5 @@
   exitcode=1; echo positional parameters were not saved.
 fi
-test x\$exitcode = x0 || exit 1
-test -x / || exit 1"
+test x\$exitcode = x0 || exit 1"
   as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
   as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
@@ -237,23 +213,19 @@
 
       if test "x$CONFIG_SHELL" != x; then :
-  export CONFIG_SHELL
-             # We cannot yet assume a decent shell, so we have to provide a
-# neutralization value for shells without unset; and this also
-# works around shells that cannot unset nonexistent variables.
-# Preserve -v and -x to the replacement shell.
-BASH_ENV=/dev/null
-ENV=/dev/null
-(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
-case $- in # ((((
-  *v*x* | *x*v* ) as_opts=-vx ;;
-  *v* ) as_opts=-v ;;
-  *x* ) as_opts=-x ;;
-  * ) as_opts= ;;
-esac
-exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
-# Admittedly, this is quite paranoid, since all the known shells bail
-# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-exit 255
+  # We cannot yet assume a decent shell, so we have to provide a
+	# neutralization value for shells without unset; and this also
+	# works around shells that cannot unset nonexistent variables.
+	# Preserve -v and -x to the replacement shell.
+	BASH_ENV=/dev/null
+	ENV=/dev/null
+	(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+	export CONFIG_SHELL
+	case $- in # ((((
+	  *v*x* | *x*v* ) as_opts=-vx ;;
+	  *v* ) as_opts=-v ;;
+	  *x* ) as_opts=-x ;;
+	  * ) as_opts= ;;
+	esac
+	exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
 fi
 
@@ -357,12 +329,4 @@
 
 } # as_fn_mkdir_p
-
-# as_fn_executable_p FILE
-# -----------------------
-# Test if FILE is an executable regular file.
-as_fn_executable_p ()
-{
-  test -f "$1" && test -x "$1"
-} # as_fn_executable_p
 # as_fn_append VAR VALUE
 # ----------------------
@@ -486,8 +450,4 @@
     { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
 
-  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
-  # already done that, so ensure we don't try to do so again and fall
-  # in an infinite loop.  This has already happened in practice.
-  _as_can_reexec=no; export _as_can_reexec
   # Don't try to exec as it changes $[0], causing all sort of problems
   # (the dirname of $[0] is not the place where we might find the
@@ -524,14 +484,14 @@
     # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
     # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-    # In both cases, we have to default to `cp -pR'.
+    # In both cases, we have to default to `cp -p'.
     ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-      as_ln_s='cp -pR'
+      as_ln_s='cp -p'
   elif ln conf$$.file conf$$ 2>/dev/null; then
     as_ln_s=ln
   else
-    as_ln_s='cp -pR'
+    as_ln_s='cp -p'
   fi
 else
-  as_ln_s='cp -pR'
+  as_ln_s='cp -p'
 fi
 rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
@@ -545,6 +505,26 @@
 fi
 
-as_test_x='test -x'
-as_executable_p=as_fn_executable_p
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+	test -d "$1/.";
+      else
+	case $1 in #(
+	-*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
 
 # Sed expression to map a string onto a valid CPP name.
@@ -639,4 +619,6 @@
 openssl_h_present
 ac_no_ssl
+ac_openh264_ldflags
+ac_openh264_cflags
 ac_v4l2_ldflags
 ac_v4l2_cflags
@@ -791,4 +773,6 @@
 enable_ffmpeg
 enable_v4l2
+with_openh264
+enable_openh264
 enable_ipp
 with_ipp
@@ -1271,4 +1255,6 @@
   if test "x$build_alias" = x; then
     cross_compiling=maybe
+    $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used" >&2
   elif test "x$build_alias" != "x$host_alias"; then
     cross_compiling=yes
@@ -1454,4 +1440,5 @@
   --disable-ffmpeg        Disable ffmpeg (default: not disabled)
   --disable-v4l2          Disable Video4Linux2 (default: not disabled)
+  --disable-openh264      Disable OpenH264 (default: not disabled)
   --enable-ipp            Enable Intel IPP support. Specify the Intel IPP
                           package and samples location using IPPROOT and
@@ -1492,4 +1479,5 @@
   --with-sdl=DIR          Specify alternate libSDL prefix
   --with-ffmpeg=DIR       Specify alternate FFMPEG prefix
+  --with-openh264=DIR     Specify alternate OpenH264 prefix
   --with-ipp=DIR          Specify the Intel IPP location
   --with-ipp-samples=DIR  Specify the Intel IPP samples location
@@ -1584,7 +1572,7 @@
   cat <<\_ACEOF
 pjproject configure 2.x
-generated by GNU Autoconf 2.69
-
-Copyright (C) 2012 Free Software Foundation, Inc.
+generated by GNU Autoconf 2.68
+
+Copyright (C) 2010 Free Software Foundation, Inc.
 This configure script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it.
@@ -1700,5 +1688,5 @@
        } && test -s conftest$ac_exeext && {
 	 test "$cross_compiling" = yes ||
-	 test -x conftest$ac_exeext
+	 $as_test_x conftest$ac_exeext
        }; then :
   ac_retval=0
@@ -1987,5 +1975,5 @@
 
 It was created by pjproject $as_me 2.x, which was
-generated by GNU Autoconf 2.69.  Invocation command line was
+generated by GNU Autoconf 2.68.  Invocation command line was
 
   $ $0 $@
@@ -2512,5 +2500,5 @@
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_CC="${ac_tool_prefix}gcc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
@@ -2552,5 +2540,5 @@
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_ac_ct_CC="gcc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
@@ -2605,5 +2593,5 @@
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_CC="${ac_tool_prefix}cc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
@@ -2646,5 +2634,5 @@
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
@@ -2704,5 +2692,5 @@
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
@@ -2748,5 +2736,5 @@
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_ac_ct_CC="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
@@ -3194,5 +3182,6 @@
 #include <stdarg.h>
 #include <stdio.h>
-struct stat;
+#include <sys/types.h>
+#include <sys/stat.h>
 /* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
 struct buf { int x; };
@@ -3307,5 +3296,5 @@
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
@@ -3351,5 +3340,5 @@
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_ac_ct_CXX="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
@@ -3560,5 +3549,5 @@
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
@@ -3600,5 +3589,5 @@
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_ac_ct_RANLIB="ranlib"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
@@ -3654,5 +3643,5 @@
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
@@ -3698,5 +3687,5 @@
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_ac_ct_AR="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
@@ -4480,5 +4469,5 @@
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
-      as_fn_executable_p "$ac_path_GREP" || continue
+      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
 # Check for GNU ac_path_GREP and select it if it is found.
   # Check for GNU $ac_path_GREP
@@ -4546,5 +4535,5 @@
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
-      as_fn_executable_p "$ac_path_EGREP" || continue
+      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
 # Check for GNU ac_path_EGREP and select it if it is found.
   # Check for GNU $ac_path_EGREP
@@ -6513,5 +6502,5 @@
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_path_SDL_CONFIG="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
@@ -6559,5 +6548,5 @@
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_path_SDL_CONFIG="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
@@ -6664,5 +6653,5 @@
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
     ac_cv_prog_PKG_CONFIG="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
@@ -7065,4 +7054,92 @@
 
 fi
+
+
+
+# Check whether --with-openh264 was given.
+if test "${with_openh264+set}" = set; then :
+  withval=$with_openh264;
+else
+  with_openh264=no
+
+fi
+
+
+if test "x$ac_cross_compile" != "x" -a "x$with_openh264" = "xno"; then
+    enable_openh264=no
+fi
+
+
+
+# Check whether --enable-openh264 was given.
+if test "${enable_openh264+set}" = set; then :
+  enableval=$enable_openh264;
+		if test "$enable_openh264" = "no"; then
+		  { $as_echo "$as_me:${as_lineno-$LINENO}: result: Checking if OpenH264 is disabled... yes" >&5
+$as_echo "Checking if OpenH264 is disabled... yes" >&6; }
+		fi
+
+else
+
+		  if test "x$with_openh264" != "xno" -a "x$with_openh264" != "x"; then
+		        OPENH264_PREFIX=$with_openh264
+		  	OPENH264_CFLAGS="-I$OPENH264_PREFIX/include"
+			OPENH264_LDFLAGS="-L$OPENH264_PREFIX/lib"
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Using OpenH264 prefix... $with_openh264" >&5
+$as_echo "Using OpenH264 prefix... $with_openh264" >&6; }
+		  else
+		  	OPENH264_CFLAGS=""
+			OPENH264_LDFLAGS=""
+		  fi
+
+		  { $as_echo "$as_me:${as_lineno-$LINENO}: checking OpenH264 availability" >&5
+$as_echo_n "checking OpenH264 availability... " >&6; }
+
+		  OPENH264_LIBS="-lwels"
+
+		  SAVED_LIBS="$LIBS"
+		  SAVED_LDFLAGS="$LDFLAGS"
+		  SAVED_CFLAGS="$CFLAGS"
+
+		  LIBS="$OPENH264_LIBS $LIBS"
+		  LDFLAGS="$OPENH264_LDFLAGS $LDFLAGS"
+		  CFLAGS="$OPENH264_CFLAGS $CFLAGS"
+
+		  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <wels/codec_api.h>
+		                                    #include <wels/codec_app_def.h>
+
+int
+main ()
+{
+int main() { CreateSVCEncoder(0); return 0; }
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+   ac_openh264_cflags="-DPJMEDIA_HAS_OPENH264_CODEC=1 $OPENH264_CFLAGS"
+		  		   ac_openh264_ldflags="$OPENH264_LDFLAGS $OPENH264_LIBS"
+		  		   { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+$as_echo "ok" >&6; }
+
+else
+
+				   LIBS="$SAVED_LIBS"
+				   LDFLAGS="$SAVED_LDFLAGS"
+				   CFLAGS="$SAVED_CFLAGS"
+		  		   { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
+$as_echo "failed" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+
+fi
+
+
 
 
@@ -8346,14 +8423,14 @@
     # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
     # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-    # In both cases, we have to default to `cp -pR'.
+    # In both cases, we have to default to `cp -p'.
     ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-      as_ln_s='cp -pR'
+      as_ln_s='cp -p'
   elif ln conf$$.file conf$$ 2>/dev/null; then
     as_ln_s=ln
   else
-    as_ln_s='cp -pR'
+    as_ln_s='cp -p'
   fi
 else
-  as_ln_s='cp -pR'
+  as_ln_s='cp -p'
 fi
 rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
@@ -8415,14 +8492,26 @@
 fi
 
-
-# as_fn_executable_p FILE
-# -----------------------
-# Test if FILE is an executable regular file.
-as_fn_executable_p ()
-{
-  test -f "$1" && test -x "$1"
-} # as_fn_executable_p
-as_test_x='test -x'
-as_executable_p=as_fn_executable_p
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+	test -d "$1/.";
+      else
+	case $1 in #(
+	-*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
 
 # Sed expression to map a string onto a valid CPP name.
@@ -8446,5 +8535,5 @@
 ac_log="
 This file was extended by pjproject $as_me 2.x, which was
-generated by GNU Autoconf 2.69.  Invocation command line was
+generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -8508,8 +8597,8 @@
 ac_cs_version="\\
 pjproject config.status 2.x
-configured by $0, generated by GNU Autoconf 2.69,
+configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2010 Free Software Foundation, Inc.
 This config.status script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it."
@@ -8599,5 +8688,5 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 if \$ac_cs_recheck; then
-  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
   shift
   \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
Index: pjproject/trunk/aconfigure.ac
===================================================================
--- pjproject/trunk/aconfigure.ac	(revision 4814)
+++ pjproject/trunk/aconfigure.ac	(revision 4815)
@@ -1096,4 +1096,71 @@
 	      ])
 
+dnl # OpenH264 alt prefix
+AC_ARG_WITH(openh264,
+            AC_HELP_STRING([--with-openh264=DIR],
+		           [Specify alternate OpenH264 prefix]),
+            [],
+            [with_openh264=no]
+            )
+
+dnl # Do not use default OpenH264 installation if we are cross-compiling
+if test "x$ac_cross_compile" != "x" -a "x$with_openh264" = "xno"; then
+    enable_openh264=no
+fi
+
+dnl # OpenH264
+AC_SUBST(ac_openh264_cflags)
+AC_SUBST(ac_openh264_ldflags)
+AC_ARG_ENABLE(openh264,
+	      AC_HELP_STRING([--disable-openh264],
+			     [Disable OpenH264 (default: not disabled)]),
+	      [
+		if test "$enable_openh264" = "no"; then
+		  AC_MSG_RESULT([Checking if OpenH264 is disabled... yes])
+		fi
+	      ],
+	      [
+		  if test "x$with_openh264" != "xno" -a "x$with_openh264" != "x"; then
+		        OPENH264_PREFIX=$with_openh264
+		  	OPENH264_CFLAGS="-I$OPENH264_PREFIX/include"
+			OPENH264_LDFLAGS="-L$OPENH264_PREFIX/lib" 
+			AC_MSG_RESULT([Using OpenH264 prefix... $with_openh264])
+		  else
+		  	OPENH264_CFLAGS=""
+			OPENH264_LDFLAGS="" 
+		  fi
+
+		  AC_MSG_CHECKING([OpenH264 availability])
+
+		  OPENH264_LIBS="-lwels"
+		  
+		  SAVED_LIBS="$LIBS"
+		  SAVED_LDFLAGS="$LDFLAGS"
+		  SAVED_CFLAGS="$CFLAGS"
+		  
+		  LIBS="$OPENH264_LIBS $LIBS"
+		  LDFLAGS="$OPENH264_LDFLAGS $LDFLAGS"
+		  CFLAGS="$OPENH264_CFLAGS $CFLAGS"
+		  
+		  AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <wels/codec_api.h>
+		                                    #include <wels/codec_app_def.h>
+					          ]],
+					          [int main() { CreateSVCEncoder(0); return 0; }]
+					         )],
+		  		 [ ac_openh264_cflags="-DPJMEDIA_HAS_OPENH264_CODEC=1 $OPENH264_CFLAGS"
+		  		   ac_openh264_ldflags="$OPENH264_LDFLAGS $OPENH264_LIBS"
+		  		   AC_MSG_RESULT(ok)
+		  		  ],
+		  		 [
+				   LIBS="$SAVED_LIBS"
+				   LDFLAGS="$SAVED_LDFLAGS"
+				   CFLAGS="$SAVED_CFLAGS"
+		  		   AC_MSG_RESULT(failed)
+		  		 ])
+
+	      ])
+
+
+
 dnl ########################################################
 dnl # Intel IPP support
Index: pjproject/trunk/build.mak.in
===================================================================
--- pjproject/trunk/build.mak.in	(revision 4814)
+++ pjproject/trunk/build.mak.in	(revision 4815)
@@ -134,5 +134,5 @@
 SDL_LDFLAGS = @ac_sdl_ldflags@
 
-# FFMPEG dlags
+# FFMPEG flags
 FFMPEG_CFLAGS = @ac_ffmpeg_cflags@ 
 FFMPEG_LDFLAGS =  @ac_ffmpeg_ldflags@
@@ -142,4 +142,8 @@
 V4L2_LDFLAGS = @ac_v4l2_ldflags@
 
+# OPENH264 flags
+OPENH264_CFLAGS = @ac_openh264_cflags@ 
+OPENH264_LDFLAGS =  @ac_openh264_ldflags@
+
 # QT
 AC_PJMEDIA_VIDEO_HAS_QT = @ac_pjmedia_video_has_qt@
@@ -151,6 +155,7 @@
 # PJMEDIA features exclusion
 PJ_VIDEO_CFLAGS += $(SDL_CFLAGS) $(FFMPEG_CFLAGS) $(V4L2_CFLAGS) $(QT_CFLAGS) \
-		   $(IOS_CFLAGS)
-PJ_VIDEO_LDFLAGS += $(SDL_LDFLAGS) $(FFMPEG_LDFLAGS) $(V4L2_LDFLAGS)
+		   $(OPENH264_CFLAGS) $(IOS_CFLAGS)
+PJ_VIDEO_LDFLAGS += $(SDL_LDFLAGS) $(FFMPEG_LDFLAGS) $(V4L2_LDFLAGS) \
+                   $(OPENH264_LDFLAGS)
 
 
Index: pjproject/trunk/pjmedia/build/Makefile
===================================================================
--- pjproject/trunk/pjmedia/build/Makefile	(revision 4814)
+++ pjproject/trunk/pjmedia/build/Makefile	(revision 4815)
@@ -135,5 +135,5 @@
 #
 export PJMEDIA_CODEC_SRCDIR = ../src/pjmedia-codec
-export PJMEDIA_CODEC_OBJS += audio_codecs.o ffmpeg_vid_codecs.o \
+export PJMEDIA_CODEC_OBJS += audio_codecs.o ffmpeg_vid_codecs.o openh264.o \
 			h263_packetizer.o h264_packetizer.o \
 			$(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \
Index: pjproject/trunk/pjmedia/include/pjmedia-codec.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia-codec.h	(revision 4814)
+++ pjproject/trunk/pjmedia/include/pjmedia-codec.h	(revision 4815)
@@ -36,4 +36,5 @@
 #include <pjmedia-codec/ipp_codecs.h>
 #include <pjmedia-codec/opencore_amr.h>
+#include <pjmedia-codec/openh264.h>
 #include <pjmedia-codec/passthrough.h>
 #include <pjmedia-codec/silk.h>
Index: pjproject/trunk/pjmedia/include/pjmedia-codec/openh264.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia-codec/openh264.h	(revision 4815)
+++ pjproject/trunk/pjmedia/include/pjmedia-codec/openh264.h	(revision 4815)
@@ -0,0 +1,69 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2014 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#ifndef __PJMEDIA_CODEC_OPENH264_H__
+#define __PJMEDIA_CODEC_OPENH264_H__
+
+#include <pjmedia-codec/types.h>
+#include <pjmedia/vid_codec.h>
+
+/**
+ * @file pjmedia-codec/openh264.h
+ * @brief Open H.264 codec
+ */
+
+
+PJ_BEGIN_DECL
+
+/**
+ * @defgroup PJMEDIA_CODEC_OPENH264 Open H.264 Codec
+ * @ingroup PJMEDIA_CODEC_VID_CODECS
+ * @{
+ */
+
+/**
+ * Initialize and register OpenH264 codec factory.
+ *
+ * @param mgr	    The video codec manager instance where this codec will
+ * 		    be registered to. Specify NULL to use default instance
+ * 		    (in that case, an instance of video codec manager must
+ * 		    have been created beforehand).
+ * @param pf	    Pool factory.
+ *
+ * @return	    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_codec_openh264_vid_init(pjmedia_vid_codec_mgr *mgr,
+                                                     pj_pool_factory *pf);
+
+/**
+ * Unregister OpenH264 video codecs factory from the video codec manager and
+ * deinitialize the codec library.
+ *
+ * @return	    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_codec_openh264_vid_deinit(void);
+
+
+/**
+ * @}  PJMEDIA_CODEC_OPENH264
+ */
+
+
+PJ_END_DECL
+
+#endif	/* __PJMEDIA_CODEC_OPENH264_H__ */
Index: pjproject/trunk/pjmedia/include/pjmedia/event.h
===================================================================
--- pjproject/trunk/pjmedia/include/pjmedia/event.h	(revision 4814)
+++ pjproject/trunk/pjmedia/include/pjmedia/event.h	(revision 4815)
@@ -241,4 +241,9 @@
 {
     /**
+     * Default flag.
+     */
+    PJMEDIA_EVENT_PUBLISH_DEFAULT,
+
+    /**
      * Publisher will only post the event to the event manager. It is the
      * event manager that will later notify all the publisher's subscribers.
Index: pjproject/trunk/pjmedia/src/pjmedia-codec/openh264.cpp
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia-codec/openh264.cpp	(revision 4815)
+++ pjproject/trunk/pjmedia/src/pjmedia-codec/openh264.cpp	(revision 4815)
@@ -0,0 +1,1080 @@
+/* $Id$ */
+/* 
+ * Copyright (C)2014 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pjmedia-codec/openh264.h>
+#include <pjmedia-codec/h264_packetizer.h>
+#include <pjmedia/vid_codec_util.h>
+#include <pjmedia/errno.h>
+#include <pj/log.h>
+
+#if defined(PJMEDIA_HAS_OPENH264_CODEC) && \
+            PJMEDIA_HAS_OPENH264_CODEC != 0 && \
+    defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
+
+/* OpenH264: */
+#include <wels/codec_api.h>
+#include <wels/codec_app_def.h>
+
+/*
+ * Constants
+ */
+#define THIS_FILE		"openh264.cpp"
+#define DEFAULT_WIDTH		720
+#define DEFAULT_HEIGHT		480
+#define DEFAULT_FPS		15
+#define DEFAULT_AVG_BITRATE	256000
+#define DEFAULT_MAX_BITRATE	256000
+
+#define MAX_RX_WIDTH		1200
+#define MAX_RX_HEIGHT		800
+
+
+/*
+ * Factory operations.
+ */
+static pj_status_t oh264_test_alloc(pjmedia_vid_codec_factory *factory,
+                                    const pjmedia_vid_codec_info *info );
+static pj_status_t oh264_default_attr(pjmedia_vid_codec_factory *factory,
+                                      const pjmedia_vid_codec_info *info,
+                                      pjmedia_vid_codec_param *attr );
+static pj_status_t oh264_enum_info(pjmedia_vid_codec_factory *factory,
+                                   unsigned *count,
+                                   pjmedia_vid_codec_info codecs[]);
+static pj_status_t oh264_alloc_codec(pjmedia_vid_codec_factory *factory,
+                                     const pjmedia_vid_codec_info *info,
+                                     pjmedia_vid_codec **p_codec);
+static pj_status_t oh264_dealloc_codec(pjmedia_vid_codec_factory *factory,
+                                       pjmedia_vid_codec *codec );
+
+
+/*
+ * Codec operations
+ */
+static pj_status_t oh264_codec_init(pjmedia_vid_codec *codec,
+                                    pj_pool_t *pool );
+static pj_status_t oh264_codec_open(pjmedia_vid_codec *codec,
+                                    pjmedia_vid_codec_param *param );
+static pj_status_t oh264_codec_close(pjmedia_vid_codec *codec);
+static pj_status_t oh264_codec_modify(pjmedia_vid_codec *codec,
+                                      const pjmedia_vid_codec_param *param);
+static pj_status_t oh264_codec_get_param(pjmedia_vid_codec *codec,
+                                         pjmedia_vid_codec_param *param);
+static pj_status_t oh264_codec_encode_begin(pjmedia_vid_codec *codec,
+                                            const pjmedia_vid_encode_opt *opt,
+                                            const pjmedia_frame *input,
+                                            unsigned out_size,
+                                            pjmedia_frame *output,
+                                            pj_bool_t *has_more);
+static pj_status_t oh264_codec_encode_more(pjmedia_vid_codec *codec,
+                                           unsigned out_size,
+                                           pjmedia_frame *output,
+                                           pj_bool_t *has_more);
+static pj_status_t oh264_codec_decode(pjmedia_vid_codec *codec,
+                                      pj_size_t count,
+                                      pjmedia_frame packets[],
+                                      unsigned out_size,
+                                      pjmedia_frame *output);
+
+/* Definition for OpenH264 codecs operations. */
+static pjmedia_vid_codec_op oh264_codec_op =
+{
+    &oh264_codec_init,
+    &oh264_codec_open,
+    &oh264_codec_close,
+    &oh264_codec_modify,
+    &oh264_codec_get_param,
+    &oh264_codec_encode_begin,
+    &oh264_codec_encode_more,
+    &oh264_codec_decode,
+    NULL
+};
+
+/* Definition for OpenH264 codecs factory operations. */
+static pjmedia_vid_codec_factory_op oh264_factory_op =
+{
+    &oh264_test_alloc,
+    &oh264_default_attr,
+    &oh264_enum_info,
+    &oh264_alloc_codec,
+    &oh264_dealloc_codec
+};
+
+
+static struct oh264_factory
+{
+    pjmedia_vid_codec_factory    base;
+    pjmedia_vid_codec_mgr	*mgr;
+    pj_pool_factory             *pf;
+    pj_pool_t		        *pool;
+} oh264_factory;
+
+
+typedef struct oh264_codec_data
+{
+    pj_pool_t			*pool;
+    pjmedia_vid_codec_param	*prm;
+    pj_bool_t			 whole;
+    pjmedia_h264_packetizer	*pktz;
+
+    /* Encoder state */
+    ISVCEncoder			*enc;
+    SSourcePicture		*esrc_pic;
+    unsigned		 	 enc_input_size;
+    pj_uint8_t			*enc_frame_whole;
+    unsigned			 enc_frame_size;
+    unsigned			 enc_processed;
+    pj_timestamp		 ets;
+    SFrameBSInfo		 bsi;
+    int			 	 ilayer;
+
+    /* Decoder state */
+    ISVCDecoder			*dec;
+    pj_uint8_t			*dec_buf;
+    unsigned			 dec_buf_size;
+} oh264_codec_data;
+
+struct SLayerPEncCtx
+{
+  pj_int32_t			iDLayerQp;
+  SSliceConfig			sSliceCfg;
+};
+
+PJ_DEF(pj_status_t) pjmedia_codec_openh264_vid_init(pjmedia_vid_codec_mgr *mgr,
+                                                    pj_pool_factory *pf)
+{
+    const pj_str_t h264_name = { (char*)"H264", 4};
+    pj_status_t status;
+
+    if (oh264_factory.pool != NULL) {
+	/* Already initialized. */
+	return PJ_SUCCESS;
+    }
+
+    if (!mgr) mgr = pjmedia_vid_codec_mgr_instance();
+    PJ_ASSERT_RETURN(mgr, PJ_EINVAL);
+
+    /* Create OpenH264 codec factory. */
+    oh264_factory.base.op = &oh264_factory_op;
+    oh264_factory.base.factory_data = NULL;
+    oh264_factory.mgr = mgr;
+    oh264_factory.pf = pf;
+    oh264_factory.pool = pj_pool_create(pf, "oh264factory", 256, 256, NULL);
+    if (!oh264_factory.pool)
+	return PJ_ENOMEM;
+
+    /* Registering format match for SDP negotiation */
+    status = pjmedia_sdp_neg_register_fmt_match_cb(
+					&h264_name,
+					&pjmedia_vid_codec_h264_match_sdp);
+    pj_assert(status == PJ_SUCCESS);
+
+    /* Register codec factory to codec manager. */
+    status = pjmedia_vid_codec_mgr_register_factory(mgr,
+						    &oh264_factory.base);
+
+    PJ_LOG(4,(THIS_FILE, "OpenH264 codec initialized"));
+
+    /* Done. */
+    return PJ_SUCCESS;
+
+on_error:
+    pj_pool_release(oh264_factory.pool);
+    oh264_factory.pool = NULL;
+    return status;
+}
+
+/*
+ * Unregister OpenH264 codecs factory from pjmedia endpoint.
+ */
+PJ_DEF(pj_status_t) pjmedia_codec_openh264_vid_deinit(void)
+{
+    pj_status_t status = PJ_SUCCESS;
+
+    if (oh264_factory.pool == NULL) {
+	/* Already deinitialized */
+	return PJ_SUCCESS;
+    }
+
+    /* Unregister OpenH264 codecs factory. */
+    status = pjmedia_vid_codec_mgr_unregister_factory(oh264_factory.mgr,
+						      &oh264_factory.base);
+
+    /* Destroy pool. */
+    pj_pool_release(oh264_factory.pool);
+    oh264_factory.pool = NULL;
+
+    return status;
+}
+
+static pj_status_t oh264_test_alloc(pjmedia_vid_codec_factory *factory,
+                                    const pjmedia_vid_codec_info *info )
+{
+    PJ_ASSERT_RETURN(factory == &oh264_factory.base, PJ_EINVAL);
+
+    if (info->fmt_id == PJMEDIA_FORMAT_H264 &&
+	info->pt != 0)
+    {
+	return PJ_SUCCESS;
+    }
+
+    return PJMEDIA_CODEC_EUNSUP;
+}
+
+static pj_status_t oh264_default_attr(pjmedia_vid_codec_factory *factory,
+                                      const pjmedia_vid_codec_info *info,
+                                      pjmedia_vid_codec_param *attr )
+{
+    PJ_ASSERT_RETURN(factory == &oh264_factory.base, PJ_EINVAL);
+    PJ_ASSERT_RETURN(info && attr, PJ_EINVAL);
+
+    pj_bzero(attr, sizeof(pjmedia_vid_codec_param));
+
+    attr->dir = PJMEDIA_DIR_ENCODING_DECODING;
+    attr->packing = PJMEDIA_VID_PACKING_PACKETS;
+
+    /* Encoded format */
+    pjmedia_format_init_video(&attr->enc_fmt, PJMEDIA_FORMAT_H264,
+                              DEFAULT_WIDTH, DEFAULT_HEIGHT,
+			      DEFAULT_FPS, 1);
+
+    /* Decoded format */
+    pjmedia_format_init_video(&attr->dec_fmt, PJMEDIA_FORMAT_I420,
+                              DEFAULT_WIDTH, DEFAULT_HEIGHT,
+			      DEFAULT_FPS, 1);
+
+    /* Decoding fmtp */
+    attr->dec_fmtp.cnt = 2;
+    attr->dec_fmtp.param[0].name = pj_str((char*)"profile-level-id");
+    attr->dec_fmtp.param[0].val = pj_str((char*)"42e01e");
+    attr->dec_fmtp.param[1].name = pj_str((char*)" packetization-mode");
+    attr->dec_fmtp.param[1].val = pj_str((char*)"1");
+
+    /* Bitrate */
+    attr->enc_fmt.det.vid.avg_bps = DEFAULT_AVG_BITRATE;
+    attr->enc_fmt.det.vid.max_bps = DEFAULT_MAX_BITRATE;
+
+    /* Encoding MTU */
+    attr->enc_mtu = PJMEDIA_MAX_VID_PAYLOAD_SIZE;
+
+    return PJ_SUCCESS;
+}
+
+static pj_status_t oh264_enum_info(pjmedia_vid_codec_factory *factory,
+                                   unsigned *count,
+                                   pjmedia_vid_codec_info info[])
+{
+    PJ_ASSERT_RETURN(info && *count > 0, PJ_EINVAL);
+    PJ_ASSERT_RETURN(factory == &oh264_factory.base, PJ_EINVAL);
+
+    *count = 1;
+    info->fmt_id = PJMEDIA_FORMAT_H264;
+    info->pt = PJMEDIA_RTP_PT_H264;
+    info->encoding_name = pj_str((char*)"H264");
+    info->encoding_desc = pj_str((char*)"OpenH264 codec");
+    info->clock_rate = 90000;
+    info->dir = PJMEDIA_DIR_ENCODING_DECODING;
+    info->dec_fmt_id_cnt = 1;
+    info->dec_fmt_id[0] = PJMEDIA_FORMAT_I420;
+    info->packings = PJMEDIA_VID_PACKING_PACKETS |
+		     PJMEDIA_VID_PACKING_WHOLE;
+    info->fps_cnt = 3;
+    info->fps[0].num = 15;
+    info->fps[0].denum = 1;
+    info->fps[1].num = 25;
+    info->fps[1].denum = 1;
+    info->fps[2].num = 30;
+    info->fps[2].denum = 1;
+
+    return PJ_SUCCESS;
+
+}
+
+static pj_status_t oh264_alloc_codec(pjmedia_vid_codec_factory *factory,
+                                     const pjmedia_vid_codec_info *info,
+                                     pjmedia_vid_codec **p_codec)
+{
+    pj_pool_t *pool;
+    pjmedia_vid_codec *codec;
+    oh264_codec_data *oh264_data;
+    int rc;
+
+    PJ_ASSERT_RETURN(factory == &oh264_factory.base && info && p_codec,
+                     PJ_EINVAL);
+
+    *p_codec = NULL;
+
+    pool = pj_pool_create(oh264_factory.pf, "oh264%p", 512, 512, NULL);
+    if (!pool)
+	return PJ_ENOMEM;
+
+    /* codec instance */
+    codec = PJ_POOL_ZALLOC_T(pool, pjmedia_vid_codec);
+    codec->factory = factory;
+    codec->op = &oh264_codec_op;
+
+    /* codec data */
+    oh264_data = PJ_POOL_ZALLOC_T(pool, oh264_codec_data);
+    oh264_data->pool = pool;
+    codec->codec_data = oh264_data;
+
+    /* encoder allocation */
+    rc = CreateSVCEncoder(&oh264_data->enc);
+    if (rc != 0)
+	goto on_error;
+
+    oh264_data->esrc_pic = PJ_POOL_ZALLOC_T(pool, SSourcePicture);
+
+    /* decoder allocation */
+    rc = CreateDecoder(&oh264_data->dec);
+    if (rc != 0)
+	goto on_error;
+
+    *p_codec = codec;
+    return PJ_SUCCESS;
+
+on_error:
+    oh264_dealloc_codec(factory, codec);
+    return PJMEDIA_CODEC_EFAILED;
+}
+
+static pj_status_t oh264_dealloc_codec(pjmedia_vid_codec_factory *factory,
+                                       pjmedia_vid_codec *codec )
+{
+    oh264_codec_data *oh264_data;
+
+    PJ_ASSERT_RETURN(codec, PJ_EINVAL);
+
+    oh264_data = (oh264_codec_data*) codec->codec_data;
+    if (oh264_data->enc) {
+	DestroySVCEncoder(oh264_data->enc);
+	oh264_data->enc = NULL;
+    }
+    if (oh264_data->dec) {
+	oh264_data->dec->Uninitialize();
+    	DestroyDecoder(oh264_data->dec);
+    	oh264_data->dec = NULL;
+    }
+    pj_pool_release(oh264_data->pool);
+    return PJ_SUCCESS;
+}
+
+static pj_status_t oh264_codec_init(pjmedia_vid_codec *codec,
+                                    pj_pool_t *pool )
+{
+    PJ_ASSERT_RETURN(codec && pool, PJ_EINVAL);
+    PJ_UNUSED_ARG(codec);
+    PJ_UNUSED_ARG(pool);
+    return PJ_SUCCESS;
+}
+
+static pj_status_t oh264_codec_open(pjmedia_vid_codec *codec,
+                                    pjmedia_vid_codec_param *codec_param )
+{
+    oh264_codec_data 	*oh264_data;
+    pjmedia_vid_codec_param	*param;
+    pjmedia_h264_packetizer_cfg  pktz_cfg;
+    pjmedia_vid_codec_h264_fmtp  h264_fmtp;
+    SEncParamExt	 eprm;
+    SSpatialLayerConfig *elayer = &eprm.sSpatialLayers[0];
+    SLayerPEncCtx	 elayer_ctx;
+    SDecodingParam	 sDecParam = {0};
+    int 		 rc;
+    pj_status_t		 status;
+
+    PJ_ASSERT_RETURN(codec && codec_param, PJ_EINVAL);
+
+    PJ_LOG(5,(THIS_FILE, "Opening codec.."));
+
+    oh264_data = (oh264_codec_data*) codec->codec_data;
+    oh264_data->prm = pjmedia_vid_codec_param_clone( oh264_data->pool,
+                                                     codec_param);
+    param = oh264_data->prm;
+
+    /* Parse remote fmtp */
+    pj_bzero(&h264_fmtp, sizeof(h264_fmtp));
+    status = pjmedia_vid_codec_h264_parse_fmtp(&param->enc_fmtp, &h264_fmtp);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    /* Apply SDP fmtp to format in codec param */
+    if (!param->ignore_fmtp) {
+	status = pjmedia_vid_codec_h264_apply_fmtp(param);
+	if (status != PJ_SUCCESS)
+	    return status;
+    }
+
+    pj_bzero(&pktz_cfg, sizeof(pktz_cfg));
+    pktz_cfg.mtu = param->enc_mtu;
+    /* Packetization mode */
+#if 0
+    if (h264_fmtp.packetization_mode == 0)
+	pktz_cfg.mode = PJMEDIA_H264_PACKETIZER_MODE_SINGLE_NAL;
+    else if (h264_fmtp.packetization_mode == 1)
+	pktz_cfg.mode = PJMEDIA_H264_PACKETIZER_MODE_NON_INTERLEAVED;
+    else
+	return PJ_ENOTSUP;
+#else
+    if (h264_fmtp.packetization_mode!=
+				PJMEDIA_H264_PACKETIZER_MODE_SINGLE_NAL &&
+	h264_fmtp.packetization_mode!=
+				PJMEDIA_H264_PACKETIZER_MODE_NON_INTERLEAVED)
+    {
+	return PJ_ENOTSUP;
+    }
+    /* Better always send in single NAL mode for better compatibility */
+    pktz_cfg.mode = PJMEDIA_H264_PACKETIZER_MODE_SINGLE_NAL;
+#endif
+
+    status = pjmedia_h264_packetizer_create(oh264_data->pool, &pktz_cfg,
+                                            &oh264_data->pktz);
+    if (status != PJ_SUCCESS)
+	return status;
+
+    oh264_data->whole = (param->packing == PJMEDIA_VID_PACKING_WHOLE);
+
+    /*
+     * Encoder
+     */
+
+    /* Init encoder parameters */
+    pj_bzero(&eprm, sizeof(eprm));
+    eprm.iInputCsp			= videoFormatI420;
+    eprm.sSpatialLayers[0].uiProfileIdc	= 66;	// PRO_BASELINE
+    eprm.iPicWidth			= param->enc_fmt.det.vid.size.w;
+    eprm.iPicHeight			= param->enc_fmt.det.vid.size.h;
+    eprm.fMaxFrameRate			= (param->enc_fmt.det.vid.fps.num * 1.0 /
+					   param->enc_fmt.det.vid.fps.denum);
+    eprm.uiFrameToBeCoded		= -1;
+    eprm.iTemporalLayerNum		= 1;
+    eprm.uiIntraPeriod			= 0; /* I-Frame interval in frames */
+    eprm.bEnableSpsPpsIdAddition	= (oh264_data->whole? false : true);
+    eprm.bEnableFrameCroppingFlag	= true;
+    eprm.iLoopFilterDisableIdc		= 0;
+    eprm.iLoopFilterAlphaC0Offset	= 0;
+    eprm.iLoopFilterBetaOffset		= 0;
+    eprm.iMultipleThreadIdc		= 1;
+    eprm.bEnableRc			= 1;
+    eprm.iTargetBitrate			= param->enc_fmt.det.vid.avg_bps;
+    eprm.bEnableFrameSkip		= 1;
+    eprm.bEnableDenoise			= 0;
+    eprm.bEnableSceneChangeDetect	= 1;
+    eprm.bEnableBackgroundDetection	= 1;
+    eprm.bEnableAdaptiveQuant		= 1;
+    eprm.bEnableLongTermReference	= 0;
+    eprm.iLtrMarkPeriod			= 30;
+    eprm.bPrefixNalAddingCtrl		= false;
+    eprm.iSpatialLayerNum		= 1;
+
+    pj_bzero(&elayer_ctx, sizeof (SLayerPEncCtx));
+    elayer_ctx.iDLayerQp		= 24;
+    elayer_ctx.sSliceCfg.uiSliceMode	= (oh264_data->whole ?
+					    SM_SINGLE_SLICE : SM_DYN_SLICE);
+    elayer_ctx.sSliceCfg.sSliceArgument.uiSliceSizeConstraint = param->enc_mtu;
+    elayer_ctx.sSliceCfg.sSliceArgument.uiSliceNum      = 1;
+    elayer_ctx.sSliceCfg.sSliceArgument.uiSliceMbNum[0] = 960;
+    elayer_ctx.sSliceCfg.sSliceArgument.uiSliceMbNum[1] = 0;
+    elayer_ctx.sSliceCfg.sSliceArgument.uiSliceMbNum[2] = 0;
+    elayer_ctx.sSliceCfg.sSliceArgument.uiSliceMbNum[3] = 0;
+    elayer_ctx.sSliceCfg.sSliceArgument.uiSliceMbNum[4] = 0;
+    elayer_ctx.sSliceCfg.sSliceArgument.uiSliceMbNum[5] = 0;
+    elayer_ctx.sSliceCfg.sSliceArgument.uiSliceMbNum[6] = 0;
+    elayer_ctx.sSliceCfg.sSliceArgument.uiSliceMbNum[7] = 0;
+
+    elayer->iVideoWidth			= eprm.iPicWidth;
+    elayer->iVideoHeight		= eprm.iPicHeight;
+    elayer->fFrameRate			= eprm.fMaxFrameRate;
+    elayer->uiProfileIdc		= eprm.sSpatialLayers[0].uiProfileIdc;
+    elayer->iSpatialBitrate		= eprm.iTargetBitrate;
+    elayer->iDLayerQp			= elayer_ctx.iDLayerQp;
+    elayer->sSliceCfg.uiSliceMode	= elayer_ctx.sSliceCfg.uiSliceMode;
+
+    memcpy( &elayer->sSliceCfg,
+            &elayer_ctx.sSliceCfg,
+            sizeof (SSliceConfig));
+    memcpy( &elayer->sSliceCfg.sSliceArgument.uiSliceMbNum[0],
+            &elayer_ctx.sSliceCfg.sSliceArgument.uiSliceMbNum[0],
+            sizeof (elayer_ctx.sSliceCfg.sSliceArgument.uiSliceMbNum));
+
+    /* Init input picture */
+    oh264_data->esrc_pic->iColorFormat	= videoFormatI420;
+    oh264_data->esrc_pic->uiTimeStamp	= 0;
+    oh264_data->esrc_pic->iPicWidth	= eprm.iPicWidth;
+    oh264_data->esrc_pic->iPicHeight	= eprm.iPicHeight;
+    oh264_data->esrc_pic->iStride[0] 	= oh264_data->esrc_pic->iPicWidth;
+    oh264_data->esrc_pic->iStride[1]	=
+	    oh264_data->esrc_pic->iStride[2] =
+					  oh264_data->esrc_pic->iStride[0]>>1;
+
+    oh264_data->enc_input_size = oh264_data->esrc_pic->iPicWidth *
+				 oh264_data->esrc_pic->iPicHeight * 3 >> 1;
+
+    /* Initialize encoder */
+    rc = oh264_data->enc->InitializeExt (&eprm);
+    if (rc != cmResultSuccess) {
+	PJ_LOG(4,(THIS_FILE, "SVC encoder Initialize failed, rc=%d", rc));
+	return PJMEDIA_CODEC_EFAILED;
+    }
+
+    /*
+     * Decoder
+     */
+    sDecParam.sVideoProperty.size	= sizeof (sDecParam.sVideoProperty);
+    sDecParam.iOutputColorFormat	= videoFormatI420;
+    sDecParam.uiTargetDqLayer		= (pj_uint8_t) - 1;
+    sDecParam.uiEcActiveFlag		= 1;
+    sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
+
+    //TODO:
+    // Apply "sprop-parameter-sets" here
+
+    rc = CreateDecoder(&oh264_data->dec);
+    if (rc) {
+	PJ_LOG(4,(THIS_FILE, "Unable to create OpenH264 decoder"));
+	return PJMEDIA_CODEC_EFAILED;
+    }
+
+    rc = oh264_data->dec->Initialize (&sDecParam);
+    if (rc) {
+	PJ_LOG(4,(THIS_FILE, "Decoder initialization failed, rc=%d", rc));
+	return PJMEDIA_CODEC_EFAILED;
+    }
+
+    int32_t color_fmt = videoFormatI420;
+    rc = oh264_data->dec->SetOption (DECODER_OPTION_DATAFORMAT,  &color_fmt);
+    if (rc) {
+	PJ_LOG(4,(THIS_FILE,
+		 "Warning: SetOption(DECODER_OPTION_DATAFORMAT) failed, rc=%d",
+		 rc));
+    }
+
+    oh264_data->dec_buf_size = (MAX_RX_WIDTH * MAX_RX_HEIGHT * 3 >> 1) +
+			       (MAX_RX_WIDTH);
+    oh264_data->dec_buf = (pj_uint8_t*)pj_pool_alloc(oh264_data->pool,
+                                                     oh264_data->dec_buf_size);
+
+    /* Need to update param back after values are negotiated */
+    pj_memcpy(codec_param, param, sizeof(*codec_param));
+
+    return PJ_SUCCESS;
+}
+
+static pj_status_t oh264_codec_close(pjmedia_vid_codec *codec)
+{
+    PJ_ASSERT_RETURN(codec, PJ_EINVAL);
+    PJ_UNUSED_ARG(codec);
+    return PJ_SUCCESS;
+}
+
+static pj_status_t oh264_codec_modify(pjmedia_vid_codec *codec,
+                                      const pjmedia_vid_codec_param *param)
+{
+    PJ_ASSERT_RETURN(codec && param, PJ_EINVAL);
+    PJ_UNUSED_ARG(codec);
+    PJ_UNUSED_ARG(param);
+    return PJ_EINVALIDOP;
+}
+
+static pj_status_t oh264_codec_get_param(pjmedia_vid_codec *codec,
+                                         pjmedia_vid_codec_param *param)
+{
+    struct oh264_codec_data *oh264_data;
+
+    PJ_ASSERT_RETURN(codec && param, PJ_EINVAL);
+
+    oh264_data = (oh264_codec_data*) codec->codec_data;
+    pj_memcpy(param, oh264_data->prm, sizeof(*param));
+
+    return PJ_SUCCESS;
+}
+
+static pj_status_t oh264_codec_encode_begin(pjmedia_vid_codec *codec,
+                                            const pjmedia_vid_encode_opt *opt,
+                                            const pjmedia_frame *input,
+                                            unsigned out_size,
+                                            pjmedia_frame *output,
+                                            pj_bool_t *has_more)
+{
+    struct oh264_codec_data *oh264_data;
+    int rc;
+
+    PJ_ASSERT_RETURN(codec && input && out_size && output && has_more,
+                     PJ_EINVAL);
+
+    oh264_data = (oh264_codec_data*) codec->codec_data;
+
+    PJ_ASSERT_RETURN(input->size == oh264_data->enc_input_size,
+                     PJMEDIA_CODEC_EFRMINLEN);
+
+    if (opt && opt->force_keyframe) {
+	oh264_data->enc->ForceIntraFrame(true);
+    }
+
+    oh264_data->esrc_pic->pData[0] = (pj_uint8_t*)input->buf;
+    oh264_data->esrc_pic->pData[1] = oh264_data->esrc_pic->pData[0] +
+					(oh264_data->esrc_pic->iPicWidth *
+					 oh264_data->esrc_pic->iPicHeight);
+    oh264_data->esrc_pic->pData[2] = oh264_data->esrc_pic->pData[1] +
+					(oh264_data->esrc_pic->iPicWidth *
+					 oh264_data->esrc_pic->iPicHeight >>2);
+
+    pj_memset (&oh264_data->bsi, 0, sizeof (SFrameBSInfo));
+    rc = oh264_data->enc->EncodeFrame( oh264_data->esrc_pic, &oh264_data->bsi);
+    if (rc != cmResultSuccess) {
+	PJ_LOG(5,(THIS_FILE, "EncodeFrame() error, ret: %d", rc));
+	return PJMEDIA_CODEC_EFAILED;
+    }
+
+    if (oh264_data->bsi.eOutputFrameType == videoFrameTypeSkip) {
+	output->size = 0;
+	output->type = PJMEDIA_FRAME_TYPE_NONE;
+	output->timestamp = input->timestamp;
+	return PJ_SUCCESS;
+    }
+
+    oh264_data->ets = input->timestamp;
+    oh264_data->ilayer = 0;
+    oh264_data->enc_frame_size = oh264_data->enc_processed = 0;
+
+    if (oh264_data->whole) {
+	SLayerBSInfo* pLayerBsInfo;
+	pj_uint8_t *payload;
+	unsigned i, payload_size = 0;
+
+	*has_more = PJ_FALSE;
+
+	/* Find which layer with biggest payload */
+	oh264_data->ilayer = 0;
+	payload_size = oh264_data->bsi.sLayerInfo[0].iNalLengthInByte[0];
+	for (i=0; i < (unsigned)oh264_data->bsi.iLayerNum; ++i) {
+	    unsigned j;
+	    pLayerBsInfo = &oh264_data->bsi.sLayerInfo[i];
+	    for (j=0; j < (unsigned)pLayerBsInfo->iNalCount; ++j) {
+		if (pLayerBsInfo->iNalLengthInByte[j] > (int)payload_size) {
+		    payload_size = pLayerBsInfo->iNalLengthInByte[j];
+		    oh264_data->ilayer = i;
+		}
+	    }
+	}
+
+	pLayerBsInfo = &oh264_data->bsi.sLayerInfo[oh264_data->ilayer];
+	if (pLayerBsInfo == NULL) {
+	    output->size = 0;
+	    output->type = PJMEDIA_FRAME_TYPE_NONE;
+	    return PJ_SUCCESS;
+	}
+
+	payload = pLayerBsInfo->pBsBuf;
+	payload_size = 0;
+	for (int inal = pLayerBsInfo->iNalCount - 1; inal >= 0; --inal) {
+	    payload_size += pLayerBsInfo->iNalLengthInByte[inal];
+	}
+
+	if (payload_size > out_size)
+	    return PJMEDIA_CODEC_EFRMTOOSHORT;
+
+	output->type = PJMEDIA_FRAME_TYPE_VIDEO;
+	output->size = payload_size;
+	output->timestamp = input->timestamp;
+	pj_memcpy(output->buf, payload, payload_size);
+
+	return PJ_SUCCESS;
+    }
+
+    return oh264_codec_encode_more(codec, out_size, output, has_more);
+}
+
+
+static pj_status_t oh264_codec_encode_more(pjmedia_vid_codec *codec,
+                                           unsigned out_size,
+                                           pjmedia_frame *output,
+                                           pj_bool_t *has_more)
+{
+    struct oh264_codec_data *oh264_data;
+    const pj_uint8_t *payload;
+    pj_size_t payload_len;
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(codec && out_size && output && has_more,
+                     PJ_EINVAL);
+
+    oh264_data = (oh264_codec_data*) codec->codec_data;
+
+    if (oh264_data->enc_processed < oh264_data->enc_frame_size) {
+	/* We have outstanding frame in packetizer */
+	status = pjmedia_h264_packetize(oh264_data->pktz,
+	                                oh264_data->enc_frame_whole,
+	                                oh264_data->enc_frame_size,
+	                                &oh264_data->enc_processed,
+	                                &payload, &payload_len);
+	if (status != PJ_SUCCESS) {
+	    /* Reset */
+	    oh264_data->enc_frame_size = oh264_data->enc_processed = 0;
+	    *has_more = (oh264_data->enc_processed <
+			    oh264_data->enc_frame_size) ||
+			(oh264_data->ilayer < oh264_data->bsi.iLayerNum);
+
+	    PJ_PERROR(3,(THIS_FILE, status, "pjmedia_h264_packetize() error"));
+	    return status;
+	}
+
+	PJ_ASSERT_RETURN(payload_len <= out_size, PJMEDIA_CODEC_EFRMTOOSHORT);
+
+        output->type = PJMEDIA_FRAME_TYPE_VIDEO;
+        pj_memcpy(output->buf, payload, payload_len);
+        output->size = payload_len;
+
+        if (oh264_data->bsi.eOutputFrameType == videoFrameTypeIDR) {
+	    output->bit_info |= PJMEDIA_VID_FRM_KEYFRAME;
+        }
+
+        *has_more = (oh264_data->enc_processed < oh264_data->enc_frame_size) ||
+        	    (oh264_data->ilayer < oh264_data->bsi.iLayerNum);
+        return PJ_SUCCESS;
+    }
+
+    if (oh264_data->ilayer >= oh264_data->bsi.iLayerNum) {
+	/* No more unretrieved frame */
+	goto no_frame;
+    }
+
+    SLayerBSInfo* pLayerBsInfo;
+    pLayerBsInfo = &oh264_data->bsi.sLayerInfo[oh264_data->ilayer++];
+    if (pLayerBsInfo == NULL) {
+	goto no_frame;
+    }
+
+    oh264_data->enc_frame_size = 0;
+    for (int inal = pLayerBsInfo->iNalCount - 1; inal >= 0; --inal) {
+	oh264_data->enc_frame_size += pLayerBsInfo->iNalLengthInByte[inal];
+    }
+
+    oh264_data->enc_frame_whole = pLayerBsInfo->pBsBuf;
+    oh264_data->enc_processed = 0;
+
+
+    status = pjmedia_h264_packetize(oh264_data->pktz,
+				    oh264_data->enc_frame_whole,
+				    oh264_data->enc_frame_size,
+				    &oh264_data->enc_processed,
+				    &payload, &payload_len);
+    if (status != PJ_SUCCESS) {
+	/* Reset */
+	oh264_data->enc_frame_size = oh264_data->enc_processed = 0;
+	*has_more = (oh264_data->ilayer < oh264_data->bsi.iLayerNum);
+
+	PJ_PERROR(3,(THIS_FILE, status, "pjmedia_h264_packetize() error [2]"));
+	return status;
+    }
+
+    PJ_ASSERT_RETURN(payload_len <= out_size, PJMEDIA_CODEC_EFRMTOOSHORT);
+
+    output->type = PJMEDIA_FRAME_TYPE_VIDEO;
+    pj_memcpy(output->buf, payload, payload_len);
+    output->size = payload_len;
+
+    if (oh264_data->bsi.eOutputFrameType == videoFrameTypeIDR) {
+	output->bit_info |= PJMEDIA_VID_FRM_KEYFRAME;
+    }
+
+    *has_more = (oh264_data->enc_processed < oh264_data->enc_frame_size) ||
+    	    (oh264_data->ilayer < oh264_data->bsi.iLayerNum);
+
+    return PJ_SUCCESS;
+
+no_frame:
+    *has_more = PJ_FALSE;
+    output->size = 0;
+    output->type = PJMEDIA_FRAME_TYPE_NONE;
+    return PJ_SUCCESS;
+}
+
+static int write_yuv(pj_uint8_t *buf,
+                     unsigned dst_len,
+                     unsigned char* pData[3],
+                     int iStride[2],
+                     int iWidth,
+                     int iHeight)
+{
+    unsigned req_size;
+    pj_uint8_t *dst = buf;
+    pj_uint8_t *max = dst + dst_len;
+    int   i;
+    unsigned char*  pPtr = NULL;
+
+    req_size = (iWidth * iHeight) + (iWidth / 2 * iHeight / 2) +
+	       (iWidth / 2 * iHeight / 2);
+    if (dst_len < req_size)
+	return -1;
+
+    pPtr = pData[0];
+    for (i = 0; i < iHeight && (dst + iWidth < max); i++) {
+	pj_memcpy(dst, pPtr, iWidth);
+	pPtr += iStride[0];
+	dst += iWidth;
+    }
+
+    if (i < iHeight)
+	return -1;
+
+    iHeight = iHeight / 2;
+    iWidth = iWidth / 2;
+    pPtr = pData[1];
+    for (i = 0; i < iHeight && (dst + iWidth <= max); i++) {
+	pj_memcpy(dst, pPtr, iWidth);
+	pPtr += iStride[1];
+	dst += iWidth;
+    }
+
+    if (i < iHeight)
+	return -1;
+
+    pPtr = pData[2];
+    for (i = 0; i < iHeight && (dst + iWidth <= max); i++) {
+	pj_memcpy(dst, pPtr, iWidth);
+	pPtr += iStride[1];
+	dst += iWidth;
+    }
+
+    if (i < iHeight)
+	return -1;
+
+    return dst - buf;
+}
+
+static pj_status_t oh264_got_decoded_frame(pjmedia_vid_codec *codec,
+					   struct oh264_codec_data *oh264_data,
+					   void *pData[3],
+					   SBufferInfo *sDstBufInfo,
+					   pj_timestamp *timestamp,
+					   unsigned out_size,
+					   pjmedia_frame *output)
+{
+    pj_uint8_t* pDst[3] = {NULL};
+
+    pDst[0] = (pj_uint8_t*)pData[0];
+    pDst[1] = (pj_uint8_t*)pData[1];
+    pDst[2] = (pj_uint8_t*)pData[2];
+
+    /* Do not reset size as it may already contain frame
+    output->size = 0;
+    */
+
+    if (!pDst[0] || !pDst[1] || !pDst[2]) {
+	return PJ_SUCCESS;
+    }
+
+    int iStride[2];
+    int iWidth = sDstBufInfo->UsrData.sSystemBuffer.iWidth;
+    int iHeight = sDstBufInfo->UsrData.sSystemBuffer.iHeight;
+
+    iStride[0] = sDstBufInfo->UsrData.sSystemBuffer.iStride[0];
+    iStride[1] = sDstBufInfo->UsrData.sSystemBuffer.iStride[1];
+
+    int len = write_yuv((pj_uint8_t *)output->buf, out_size,
+			pDst, iStride, iWidth, iHeight);
+    if (len > 0) {
+	output->timestamp = *timestamp;
+	output->size = len;
+	output->type = PJMEDIA_FRAME_TYPE_VIDEO;
+    } else {
+	/* buffer is damaged, reset size */
+	output->size = 0;
+	return PJMEDIA_CODEC_EFRMTOOSHORT;
+    }
+
+    /* Detect format change */
+    if (iWidth != (int)oh264_data->prm->dec_fmt.det.vid.size.w ||
+	iHeight != (int)oh264_data->prm->dec_fmt.det.vid.size.h)
+    {
+	pjmedia_event event;
+
+	PJ_LOG(4,(THIS_FILE, "Frame size changed: %dx%d --> %dx%d",
+		  oh264_data->prm->dec_fmt.det.vid.size.w,
+		  oh264_data->prm->dec_fmt.det.vid.size.h,
+		  iWidth, iHeight));
+
+	oh264_data->prm->dec_fmt.det.vid.size.w = iWidth;
+	oh264_data->prm->dec_fmt.det.vid.size.h = iHeight;
+
+	/* Broadcast format changed event */
+	pjmedia_event_init(&event, PJMEDIA_EVENT_FMT_CHANGED,
+	                   timestamp, codec);
+	event.data.fmt_changed.dir = PJMEDIA_DIR_DECODING;
+	pjmedia_format_copy(&event.data.fmt_changed.new_fmt,
+	                    &oh264_data->prm->dec_fmt);
+	pjmedia_event_publish(NULL, codec, &event,
+	                      PJMEDIA_EVENT_PUBLISH_DEFAULT);
+    }
+
+    return PJ_SUCCESS;
+}
+
+static pj_status_t oh264_codec_decode(pjmedia_vid_codec *codec,
+                                      pj_size_t count,
+                                      pjmedia_frame packets[],
+                                      unsigned out_size,
+                                      pjmedia_frame *output)
+{
+    struct oh264_codec_data *oh264_data;
+    void* pData[3] = {NULL};
+    const pj_uint8_t nal_start[] = { 0, 0, 1 };
+    SBufferInfo sDstBufInfo;
+    pj_bool_t has_frame = PJ_FALSE;
+    unsigned buf_pos, whole_len = 0;
+    unsigned i, frm_cnt;
+    pj_status_t status = PJ_SUCCESS;
+
+    PJ_ASSERT_RETURN(codec && count && packets && out_size && output,
+                     PJ_EINVAL);
+    PJ_ASSERT_RETURN(output->buf, PJ_EINVAL);
+
+    oh264_data = (oh264_codec_data*) codec->codec_data;
+
+    /*
+     * Step 1: unpacketize the packets/frames
+     */
+    whole_len = 0;
+    if (oh264_data->whole) {
+	for (i=0; i<count; ++i) {
+	    if (whole_len + packets[i].size > oh264_data->dec_buf_size) {
+		PJ_LOG(4,(THIS_FILE, "Decoding buffer overflow [1]"));
+		return PJMEDIA_CODEC_EFRMTOOSHORT;
+	    }
+
+	    pj_memcpy( oh264_data->dec_buf + whole_len,
+	               (pj_uint8_t*)packets[i].buf,
+	               packets[i].size);
+	    whole_len += packets[i].size;
+	}
+
+    } else {
+	for (i=0; i<count; ++i) {
+
+	    if (whole_len + packets[i].size + sizeof(nal_start) >
+						oh264_data->dec_buf_size)
+	    {
+		PJ_LOG(4,(THIS_FILE, "Decoding buffer overflow [1]"));
+		return PJMEDIA_CODEC_EFRMTOOSHORT;
+	    }
+
+	    status = pjmedia_h264_unpacketize( oh264_data->pktz,
+					       (pj_uint8_t*)packets[i].buf,
+					       packets[i].size,
+					       oh264_data->dec_buf,
+					       oh264_data->dec_buf_size,
+					       &whole_len);
+	    if (status != PJ_SUCCESS) {
+		PJ_PERROR(4,(THIS_FILE, status, "Unpacketize error"));
+		continue;
+	    }
+	}
+    }
+
+    if (whole_len + sizeof(nal_start) > oh264_data->dec_buf_size) {
+	PJ_LOG(4,(THIS_FILE, "Decoding buffer overflow [2]"));
+	return PJMEDIA_CODEC_EFRMTOOSHORT;
+    }
+
+    /* Dummy NAL sentinel */
+    pj_memcpy( oh264_data->dec_buf + whole_len, nal_start, sizeof(nal_start));
+
+    /*
+     * Step 2: parse the individual NAL and give to decoder
+     */
+    buf_pos = 0;
+    for ( frm_cnt=0; ; ++frm_cnt) {
+	unsigned frm_size;
+	unsigned char *start;
+
+	for (i = 0; buf_pos + i < whole_len; i++) {
+	    if (oh264_data->dec_buf[buf_pos + i] == 0 &&
+		oh264_data->dec_buf[buf_pos + i + 1] == 0 &&
+		oh264_data->dec_buf[buf_pos + i + 2] == 1 &&
+		i > 1)
+	    {
+		break;
+	    }
+	}
+	frm_size = i;
+
+	pj_bzero( pData, sizeof(pData));
+	pj_bzero( &sDstBufInfo, sizeof (SBufferInfo));
+
+	start = oh264_data->dec_buf + buf_pos;
+
+	/* Decode */
+	oh264_data->dec->DecodeFrame2( start, frm_size, pData, &sDstBufInfo);
+
+	if (sDstBufInfo.iBufferStatus == 1) {
+	    /* May overwrite existing frame but that's ok. */
+	    status = oh264_got_decoded_frame(codec, oh264_data, pData,
+	                                     &sDstBufInfo,
+	                                     &packets[0].timestamp, out_size,
+	                                     output);
+	    has_frame = (status==PJ_SUCCESS && output->size != 0);
+	}
+
+	if (buf_pos + frm_size >= whole_len)
+	    break;
+
+	buf_pos += frm_size;
+    }
+
+    /* Signal that we have no more frames */
+    int32_t iEndOfStreamFlag;
+    iEndOfStreamFlag = true;
+    oh264_data->dec->SetOption( DECODER_OPTION_END_OF_STREAM,
+                                (void*)&iEndOfStreamFlag);
+
+    /* Retrieve the decoded frame */
+    pj_bzero(pData, sizeof(pData));
+    pj_bzero(&sDstBufInfo, sizeof (SBufferInfo));
+    oh264_data->dec->DecodeFrame2 (NULL, 0, pData, &sDstBufInfo);
+
+    if (sDstBufInfo.iBufferStatus == 1) {
+	/* Overwrite existing output frame and that's ok, because we assume
+	 * newer frame have better quality because it has more NALs
+	 */
+	status = oh264_got_decoded_frame(codec, oh264_data, pData,
+	                                 &sDstBufInfo, &packets[0].timestamp,
+	                                 out_size, output);
+	has_frame = (status==PJ_SUCCESS && output->size != 0);
+    }
+
+    if (!has_frame) {
+	pjmedia_event event;
+
+	/* Broadcast missing keyframe event */
+	pjmedia_event_init(&event, PJMEDIA_EVENT_KEYFRAME_MISSING,
+	                   &packets[0].timestamp, codec);
+	pjmedia_event_publish(NULL, codec, &event,
+	                      PJMEDIA_EVENT_PUBLISH_DEFAULT);
+
+	PJ_LOG(5,(THIS_FILE, "Decode couldn't produce picture, "
+		  "input nframes=%d, concatenated size=%d bytes",
+		  count, whole_len));
+
+	output->type = PJMEDIA_FRAME_TYPE_NONE;
+	output->size = 0;
+	output->timestamp = packets[0].timestamp;
+    }
+
+    return status;
+}
+
+#endif	/* PJMEDIA_HAS_OPENH264_CODEC */
Index: pjproject/trunk/pjmedia/src/pjmedia/vid_codec_util.c
===================================================================
--- pjproject/trunk/pjmedia/src/pjmedia/vid_codec_util.c	(revision 4814)
+++ pjproject/trunk/pjmedia/src/pjmedia/vid_codec_util.c	(revision 4815)
@@ -632,5 +632,5 @@
 
     /* Calculate maximum size (in macroblocks) */
-    max_fs = fmtp->max_mbps * fps->denum / fps->num;
+    max_fs = fmtp->max_mbps * the_fps.denum / the_fps.num;
     max_fs = PJ_MIN(max_fs, fmtp->max_fs);
 
Index: pjproject/trunk/pjmedia/src/test/vid_codec_test.c
===================================================================
--- pjproject/trunk/pjmedia/src/test/vid_codec_test.c	(revision 4814)
+++ pjproject/trunk/pjmedia/src/test/vid_codec_test.c	(revision 4815)
@@ -18,5 +18,5 @@
  */
 #include "test.h"
-#include <pjmedia-codec/ffmpeg_vid_codecs.h>
+#include <pjmedia-codec.h>
 #include <pjmedia-videodev/videodev.h>
 #include <pjmedia/vid_codec.h>
@@ -298,4 +298,7 @@
         codec_param.packing = packing;
 
+        /* Don't apply SDP fmtp */
+        codec_param.ignore_fmtp = PJ_TRUE;
+
         /* Open codec */
         status = pjmedia_vid_codec_mgr_alloc_codec(NULL, codec_info,
@@ -454,4 +457,11 @@
         return -10;
 
+#if PJMEDIA_HAS_VIDEO && PJMEDIA_HAS_OPENH264_CODEC
+    status = pjmedia_codec_openh264_vid_init(NULL, mem);
+    if (status != PJ_SUCCESS) {
+	return -22;
+    }
+#endif
+
 #if PJMEDIA_HAS_FFMPEG_VID_CODEC
     status = pjmedia_codec_ffmpeg_vid_init(NULL, mem);
@@ -464,4 +474,5 @@
 	goto on_return;
 
+#if PJMEDIA_HAS_FFMPEG_VID_CODEC
     rc = encode_decode_test(pool, "h263-1998", PJMEDIA_VID_PACKING_WHOLE);
     if (rc != 0)
@@ -471,4 +482,16 @@
     if (rc != 0)
 	goto on_return;
+#endif
+
+#if PJMEDIA_HAS_FFMPEG_VID_CODEC || PJMEDIA_HAS_OPENH264_CODEC
+    rc = encode_decode_test(pool, "h264", PJMEDIA_VID_PACKING_WHOLE);
+    if (rc != 0)
+	goto on_return;
+
+    rc = encode_decode_test(pool, "h264", PJMEDIA_VID_PACKING_PACKETS);
+    if (rc != 0)
+	goto on_return;
+#endif
+
 
 on_return:
@@ -476,4 +499,7 @@
     pjmedia_codec_ffmpeg_vid_deinit();
 #endif
+#if defined(PJMEDIA_HAS_OPENH264_CODEC) && PJMEDIA_HAS_OPENH264_CODEC != 0
+    pjmedia_codec_openh264_vid_deinit();
+#endif
     pjmedia_vid_dev_subsys_shutdown();
     pj_pool_release(pool);
Index: pjproject/trunk/pjsip-apps/build/Samples.mak
===================================================================
--- pjproject/trunk/pjsip-apps/build/Samples.mak	(revision 4814)
+++ pjproject/trunk/pjsip-apps/build/Samples.mak	(revision 4815)
@@ -46,4 +46,5 @@
 	   strerror \
 	   tonegen \
+	   vid_codec_test \
 	   vid_streamutil
 
Index: pjproject/trunk/pjsip-apps/src/samples/aviplay.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/samples/aviplay.c	(revision 4814)
+++ pjproject/trunk/pjsip-apps/src/samples/aviplay.c	(revision 4815)
@@ -501,4 +501,10 @@
     }
     
+#if defined(PJMEDIA_HAS_OPENH264_CODEC) && PJMEDIA_HAS_OPENH264_CODEC != 0
+    status = pjmedia_codec_openh264_vid_init(NULL, &cp.factory);
+    if (status != PJ_SUCCESS)
+	goto on_return;
+#endif
+
 #if PJMEDIA_HAS_FFMPEG_VID_CODEC
     status = pjmedia_codec_ffmpeg_vid_init(NULL, &cp.factory);
@@ -522,4 +528,7 @@
     pjmedia_codec_ffmpeg_vid_deinit();
 #endif
+#if defined(PJMEDIA_HAS_OPENH264_CODEC) && PJMEDIA_HAS_OPENH264_CODEC != 0
+    pjmedia_codec_openh264_vid_deinit();
+#endif
     pjmedia_aud_subsys_shutdown();
     pjmedia_vid_dev_subsys_shutdown();
Index: pjproject/trunk/pjsip-apps/src/samples/simpleua.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/samples/simpleua.c	(revision 4814)
+++ pjproject/trunk/pjsip-apps/src/samples/simpleua.c	(revision 4815)
@@ -386,4 +386,9 @@
     PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
 
+#   if defined(PJMEDIA_HAS_OPENH264_CODEC) && PJMEDIA_HAS_OPENH264_CODEC != 0
+    status = pjmedia_codec_openh264_vid_init(NULL, &cp.factory);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+#   endif
+
 #  if defined(PJMEDIA_HAS_FFMPEG_VID_CODEC) && PJMEDIA_HAS_FFMPEG_VID_CODEC!=0
     /* Init ffmpeg video codecs */
@@ -576,4 +581,7 @@
 #   if defined(PJMEDIA_HAS_FFMPEG_VID_CODEC) && PJMEDIA_HAS_FFMPEG_VID_CODEC!=0
     pjmedia_codec_ffmpeg_vid_deinit();
+#   endif
+#   if defined(PJMEDIA_HAS_OPENH264_CODEC) && PJMEDIA_HAS_OPENH264_CODEC != 0
+    pjmedia_codec_openh264_vid_deinit();
 #   endif
 
Index: pjproject/trunk/pjsip-apps/src/samples/vid_codec_test.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/samples/vid_codec_test.c	(revision 4815)
+++ pjproject/trunk/pjsip-apps/src/samples/vid_codec_test.c	(revision 4815)
@@ -0,0 +1,521 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2014 Teluu Inc. (http://www.teluu.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+
+
+/**
+ * \page page_pjmedia_samples_vid_codec_test_c Samples: Video Codec Test
+ *
+ * Video codec encode and decode test.
+ *
+ * This file is pjsip-apps/src/samples/vid_vodec_test.c
+ *
+ * \includelineno vid_vodec_test.c
+ */
+
+#include <pjlib.h>
+#include <pjlib-util.h>
+#include <pjmedia.h>
+#include <pjmedia-codec.h>
+
+
+#if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0)
+
+
+#include <stdlib.h>	/* atoi() */
+#include <stdio.h>
+
+#include "util.h"
+
+
+static const char *desc = 
+ " vid_vodec_test                                                       \n"
+;
+
+#define THIS_FILE	"vid_vodec_test.c"
+
+
+/* If set, local renderer will be created to play original file */
+#define HAS_LOCAL_RENDERER_FOR_PLAY_FILE    1
+
+
+/* Default width and height for the renderer, better be set to maximum
+ * acceptable size.
+ */
+#define DEF_RENDERER_WIDTH		    640
+#define DEF_RENDERER_HEIGHT		    480
+
+
+/* Prototype */
+static void print_stream_stat(pjmedia_vid_stream *stream,
+			      const pjmedia_vid_codec_param *codec_param);
+
+/* Prototype for LIBSRTP utility in file datatypes.c */
+int hex_string_to_octet_string(char *raw, char *hex, int len);
+
+/* 
+ * Register all codecs. 
+ */
+static pj_status_t init_codecs(pj_pool_factory *pf)
+{
+    pj_status_t status;
+
+    /* To suppress warning about unused var when all codecs are disabled */
+    PJ_UNUSED_ARG(status);
+
+#if defined(PJMEDIA_HAS_OPENH264_CODEC) && PJMEDIA_HAS_OPENH264_CODEC != 0
+    status = pjmedia_codec_openh264_vid_init(NULL, pf);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+#endif
+
+#if defined(PJMEDIA_HAS_FFMPEG_VID_CODEC) && PJMEDIA_HAS_FFMPEG_VID_CODEC != 0
+    status = pjmedia_codec_ffmpeg_vid_init(NULL, pf);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+#endif
+
+    return PJ_SUCCESS;
+}
+
+/* 
+ * Register all codecs. 
+ */
+static void deinit_codecs()
+{
+#if defined(PJMEDIA_HAS_FFMPEG_VID_CODEC) && PJMEDIA_HAS_FFMPEG_VID_CODEC != 0
+    pjmedia_codec_ffmpeg_vid_deinit();
+#endif
+
+#if defined(PJMEDIA_HAS_OPENH264_CODEC) && PJMEDIA_HAS_OPENH264_CODEC != 0
+    pjmedia_codec_openh264_vid_deinit();
+#endif
+
+}
+
+/*
+ * usage()
+ */
+static void usage()
+{
+    puts(desc);
+}
+
+static void show_diff(const pj_uint8_t *buf1, const pj_uint8_t *buf2,
+                      unsigned size)
+{
+    enum {
+	STEP = 50
+    };
+    unsigned i=0;
+
+    for (; i<size; ) {
+	const pj_uint8_t *p1 = buf1 + i, *p2 = buf2 + i;
+	unsigned j;
+
+	printf("%8d ", i);
+	for (j=0; j<STEP && i+j<size; ++j) {
+	    printf(" %02x", *(p1+j));
+	}
+	printf("\n");
+	printf("         ");
+	for (j=0; j<STEP && i+j<size; ++j) {
+	    if (*(p1+j) == *(p2+j)) {
+		printf(" %02x", *(p2+j));
+	    } else {
+		printf(" %02x", *(p2+j));
+	    }
+	}
+	printf("\n");
+
+	i += j;
+    }
+}
+
+static void diff_file()
+{
+    const char *filename[2] = {
+        "/home/bennylp/Desktop/opt/src/openh264-svn/testbin/test.264",
+        "/home/bennylp/Desktop/opt/src/openh264-svn/testbin/test2.264"
+    };
+    unsigned size[2];
+    pj_uint8_t *buf[2], start_nal[3] = {0, 0, 1};
+    unsigned i, pos[2], frame_cnt, mismatch_cnt=0;
+
+    for (i=0; i<2; ++i) {
+	FILE *fhnd;
+	const pj_uint8_t start_nal[] = { 0, 0, 1};
+
+	fhnd = fopen(filename[i], "rb");
+	if (!fhnd) {
+	    printf("Error opening %s\n", filename[i]);
+	    return;
+	}
+
+	fseek(fhnd, 0, SEEK_END);
+	size[i] = ftell(fhnd);
+	fseek(fhnd, 0, SEEK_SET);
+
+	buf[i] = (pj_uint8_t*)malloc(size[i] + 4);
+	if (!buf[i])
+	    return;
+
+	if (fread (buf[i], 1, size[i], fhnd) != (unsigned)size[i]) {
+	    fprintf (stderr, "Unable to read whole file\n");
+	    return;
+	}
+
+	memcpy (buf[i] + size[i], start_nal, sizeof(start_nal));
+
+	fclose(fhnd);
+    }
+
+    if (size[0] != size[1]) {
+	printf("File size mismatch\n");
+	return;
+    }
+
+    pos[0] = pos[1] = 0;
+    for ( frame_cnt=0; ; ++frame_cnt) {
+	unsigned nal_len[2];
+	for (i = 0; i < size[0]; i++) {
+	    if (memcmp(buf[0] + pos[0] + i, start_nal,
+	               sizeof(start_nal)) == 0 && i > 0)
+	    {
+		break;
+	    }
+	}
+	nal_len[0] = i;
+	for (i = 0; i < size[1]; i++) {
+	    if (memcmp(buf[1] + pos[1] + i, start_nal,
+	               sizeof(start_nal)) == 0 && i > 0)
+	    {
+		break;
+	    }
+	}
+	nal_len[1] = i;
+
+	if (nal_len[0] != nal_len[1]) {
+	    printf("Different size in frame %d (%d vs %d)\n",
+	           frame_cnt, nal_len[0], nal_len[1]);
+	}
+
+	if (memcmp(buf[0]+pos[0], buf[1]+pos[1], nal_len[0]) != 0) {
+	    printf("Mismatch in frame %d\n", frame_cnt);
+	    show_diff(buf[0]+pos[0], buf[1]+pos[1], nal_len[0]);
+	    puts("");
+	    ++mismatch_cnt;
+	}
+
+	pos[0] += nal_len[0];
+	pos[1] += nal_len[1];
+
+	if (pos[0] >= size[0])
+	    break;
+    }
+
+    free(buf[0]);
+    free(buf[1]);
+
+    if (!mismatch_cnt)
+	puts("Files the same!");
+    else
+	printf("%d mismatches\n", mismatch_cnt);
+}
+
+/*
+ * main()
+ */
+int main(int argc, char *argv[])
+{
+    pj_caching_pool cp;
+    pjmedia_endpt *med_endpt;
+    pj_pool_t *pool;
+    pj_status_t status; 
+
+    /* Codec */
+    char *codec_id = (char*)"H264";
+    const pjmedia_vid_codec_info *codec_info;
+    pjmedia_vid_codec_param codec_param;
+    pjmedia_vid_codec *codec = NULL;
+
+    //const char *save_filename =
+    //	"/home/bennylp/Desktop/opt/src/openh264-svn/testbin/test.264";
+    const char *save_filename = NULL;
+
+    /* File */
+    enum
+    {
+	WIDTH = 320,
+	HEIGHT = 192,
+	FPS = 12,
+	YUV_SIZE = WIDTH * HEIGHT * 3 >> 1,
+	YUV_BUF_SIZE = YUV_SIZE + WIDTH,
+	MAX_FRAMES = 32,
+	MTU = 1500
+    };
+    FILE *fyuv = NULL;
+    FILE *f264 = NULL;
+    typedef pj_uint8_t enc_buf_type[MTU];
+    pj_uint8_t yuv_frame[YUV_BUF_SIZE];
+    enc_buf_type enc_buf[MAX_FRAMES];
+    unsigned read_cnt = 0,
+	     pkt_cnt = 0,
+	     dec_cnt = 0,
+	     enc_cnt;
+
+    if (0) {
+	diff_file();
+	return 1;
+    }
+
+    /* init PJLIB : */
+    status = pj_init();
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+    /* Must create a pool factory before we can allocate any memory. */
+    pj_caching_pool_init(&cp, &pj_pool_factory_default_policy, 0);
+
+    /* Initialize media endpoint. */
+    status = pjmedia_endpt_create(&cp.factory, NULL, 1, &med_endpt);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+    /* Create memory pool for application purpose */
+    pool = pj_pool_create( &cp.factory,	    /* pool factory	    */
+			   "app",	    /* pool name.	    */
+			   4000,	    /* init size	    */
+			   4000,	    /* increment size	    */
+			   NULL		    /* callback on error    */
+			   );
+
+    /* Init video format manager */
+    pjmedia_video_format_mgr_create(pool, 64, 0, NULL);
+
+    /* Init video converter manager */
+    pjmedia_converter_mgr_create(pool, NULL);
+
+    /* Init event manager */
+    pjmedia_event_mgr_create(pool, 0, NULL);
+
+    /* Init video codec manager */
+    pjmedia_vid_codec_mgr_create(pool, NULL);
+
+    /* Register all supported codecs */
+    status = init_codecs(&cp.factory);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, 1);
+
+    /* Open YUV file */
+    fyuv = fopen("pjsip-apps/bin/CiscoVT2people_320x192_12fps.yuv", "rb");
+    if (!fyuv) {
+	puts("Unable to open ../CiscoVT2people_320x192_12fps.yuv");
+	status = -1;
+	goto on_exit;
+    }
+
+    /* Write 264 file if wanted */
+    if (save_filename) {
+	f264 = fopen(save_filename, "wb");
+    }
+
+    /* Find which codec to use. */
+    if (codec_id) {
+	unsigned count = 1;
+	pj_str_t str_codec_id = pj_str(codec_id);
+
+        status = pjmedia_vid_codec_mgr_find_codecs_by_id(NULL,
+						         &str_codec_id, &count,
+						         &codec_info, NULL);
+	if (status != PJ_SUCCESS) {
+	    printf("Error: unable to find codec %s\n", codec_id);
+	    return 1;
+	}
+    } else {
+        static pjmedia_vid_codec_info info[1];
+        unsigned count = PJ_ARRAY_SIZE(info);
+
+	/* Default to first codec */
+	pjmedia_vid_codec_mgr_enum_codecs(NULL, &count, info, NULL);
+        codec_info = &info[0];
+    }
+
+    /* Get codec default param for info */
+    status = pjmedia_vid_codec_mgr_get_default_param(NULL, codec_info, 
+				                     &codec_param);
+    pj_assert(status == PJ_SUCCESS);
+    
+    /* Alloc encoder */
+    status = pjmedia_vid_codec_mgr_alloc_codec(NULL, codec_info, &codec);
+    if (status != PJ_SUCCESS) {
+	PJ_PERROR(3,(THIS_FILE, status, "Error allocating codec"));
+	goto on_exit;
+    }
+
+    codec_param.dir = PJMEDIA_DIR_ENCODING_DECODING;
+    codec_param.packing = PJMEDIA_VID_PACKING_PACKETS;
+    codec_param.enc_mtu = MTU;
+    codec_param.enc_fmt.det.vid.size.w = WIDTH;
+    codec_param.enc_fmt.det.vid.size.h = HEIGHT;
+    codec_param.enc_fmt.det.vid.fps.num = FPS;
+    codec_param.enc_fmt.det.vid.avg_bps = WIDTH * HEIGHT * FPS;
+
+    status = pjmedia_vid_codec_init(codec, pool);
+    if (status != PJ_SUCCESS) {
+	PJ_PERROR(3,(THIS_FILE, status, "Error initializing codec"));
+	goto on_exit;
+    }
+
+    status = pjmedia_vid_codec_open(codec, &codec_param);
+    if (status != PJ_SUCCESS) {
+	PJ_PERROR(3,(THIS_FILE, status, "Error opening codec"));
+	goto on_exit;
+    }
+
+    while (fread(yuv_frame, 1, YUV_SIZE, fyuv) == YUV_SIZE) {
+	pjmedia_frame frm_yuv, frm_enc[MAX_FRAMES];
+	pj_bool_t has_more = PJ_FALSE;
+	const pj_uint8_t start_nal[] = { 0, 0, 1 };
+	unsigned i;
+
+	++ read_cnt;
+
+	pj_bzero(&frm_enc, sizeof(frm_enc));
+	pj_bzero(&frm_yuv, sizeof(frm_yuv));
+
+	frm_yuv.buf = yuv_frame;
+	frm_yuv.size = YUV_SIZE;
+
+	enc_cnt = 0;
+	frm_enc[enc_cnt].buf = enc_buf[enc_cnt];
+	frm_enc[enc_cnt].size = MTU;
+
+	status = pjmedia_vid_codec_encode_begin(codec, NULL, &frm_yuv,
+	                                        MTU, &frm_enc[enc_cnt],
+	                                        &has_more);
+	if (status != PJ_SUCCESS) {
+	    PJ_PERROR(3,(THIS_FILE, status, "Codec encode error"));
+	    goto on_exit;
+	}
+	if (frm_enc[enc_cnt].size) {
+	    if (f264) {
+		fwrite(start_nal, 1, sizeof(start_nal), f264);
+		fwrite(frm_enc[enc_cnt].buf, 1, frm_enc[enc_cnt].size, f264);
+	    }
+	    ++pkt_cnt;
+	    ++enc_cnt;
+	}
+
+	while (has_more) {
+
+	    if (enc_cnt >= MAX_FRAMES) {
+		status = -1;
+		puts("Error: too many encoded frames");
+		goto on_exit;
+	    }
+
+	    has_more = PJ_FALSE;
+	    frm_enc[enc_cnt].buf = enc_buf[enc_cnt];
+	    frm_enc[enc_cnt].size = MTU;
+
+	    status = pjmedia_vid_codec_encode_more(codec, MTU,
+	                                           &frm_enc[enc_cnt],
+	                                           &has_more);
+	    if (status != PJ_SUCCESS) {
+		PJ_PERROR(3,(THIS_FILE, status, "Codec encode error"));
+		goto on_exit;
+	    }
+
+	    if (frm_enc[enc_cnt].size) {
+		if (f264) {
+		    fwrite(start_nal, 1, sizeof(start_nal), f264);
+		    fwrite(frm_enc[enc_cnt].buf, 1, frm_enc[enc_cnt].size,
+		           f264);
+		}
+		++pkt_cnt;
+		++enc_cnt;
+	    }
+	}
+
+	if (enc_cnt) {
+	    frm_yuv.buf = yuv_frame;
+	    frm_yuv.size = YUV_BUF_SIZE;
+	    status = pjmedia_vid_codec_decode(codec, enc_cnt,
+					      frm_enc,
+					      YUV_BUF_SIZE,
+					      &frm_yuv);
+	    if (status != PJ_SUCCESS) {
+		PJ_PERROR(3,(THIS_FILE, status, "Codec decode error"));
+		goto on_exit;
+	    }
+
+	    if (frm_yuv.size != 0) {
+		++dec_cnt;
+	    }
+	}
+    }
+
+    printf("Done.\n"
+	   " Read YUV frames:    %d\n"
+	   " Encoded packets:    %d\n"
+	   " Decoded YUV frames: %d\n",
+	   read_cnt, pkt_cnt, dec_cnt);
+
+    /* Start deinitialization: */
+on_exit:
+    if (codec) {
+	pjmedia_vid_codec_close(codec);
+	pjmedia_vid_codec_mgr_dealloc_codec(NULL, codec);
+    }
+
+    if (f264)
+	fclose(f264);
+
+    if (fyuv)
+	fclose(fyuv);
+
+    /* Deinit codecs */
+    deinit_codecs();
+
+    /* Destroy event manager */
+    pjmedia_event_mgr_destroy(NULL);
+
+    /* Release application pool */
+    pj_pool_release( pool );
+
+    /* Destroy media endpoint. */
+    pjmedia_endpt_destroy( med_endpt );
+
+    /* Destroy pool factory */
+    pj_caching_pool_destroy( &cp );
+
+    /* Shutdown PJLIB */
+    pj_shutdown();
+
+    return (status == PJ_SUCCESS) ? 0 : 1;
+}
+
+
+#else
+
+int main(int argc, char *argv[])
+{
+    PJ_UNUSED_ARG(argc);
+    PJ_UNUSED_ARG(argv);
+    puts("Error: this sample requires video capability "
+	    "(PJMEDIA_HAS_VIDEO == 1)");
+    return -1;
+}
+
+#endif /* PJMEDIA_HAS_VIDEO */
Index: pjproject/trunk/pjsip-apps/src/samples/vid_streamutil.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/samples/vid_streamutil.c	(revision 4814)
+++ pjproject/trunk/pjsip-apps/src/samples/vid_streamutil.c	(revision 4815)
@@ -122,4 +122,9 @@
     PJ_UNUSED_ARG(status);
 
+#if defined(PJMEDIA_HAS_OPENH264_CODEC) && PJMEDIA_HAS_OPENH264_CODEC != 0
+    status = pjmedia_codec_openh264_vid_init(NULL, pf);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+#endif
+
 #if defined(PJMEDIA_HAS_FFMPEG_VID_CODEC) && PJMEDIA_HAS_FFMPEG_VID_CODEC != 0
     status = pjmedia_codec_ffmpeg_vid_init(NULL, pf);
@@ -138,4 +143,9 @@
     pjmedia_codec_ffmpeg_vid_deinit();
 #endif
+
+#if defined(PJMEDIA_HAS_OPENH264_CODEC) && PJMEDIA_HAS_OPENH264_CODEC != 0
+    pjmedia_codec_openh264_vid_deinit();
+#endif
+
 }
 
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_vid.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_vid.c	(revision 4814)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_vid.c	(revision 4815)
@@ -74,4 +74,13 @@
     }
 
+#if PJMEDIA_HAS_VIDEO && PJMEDIA_HAS_OPENH264_CODEC
+    status = pjmedia_codec_openh264_vid_init(NULL, &pjsua_var.cp.factory);
+    if (status != PJ_SUCCESS) {
+	PJ_PERROR(1,(THIS_FILE, status,
+		     "Error initializing OpenH264 library"));
+	goto on_error;
+    }
+#endif
+
 #if PJMEDIA_HAS_VIDEO && PJMEDIA_HAS_FFMPEG_VID_CODEC
     status = pjmedia_codec_ffmpeg_vid_init(NULL, &pjsua_var.cp.factory);
@@ -132,4 +141,8 @@
 #if PJMEDIA_HAS_FFMPEG_VID_CODEC
     pjmedia_codec_ffmpeg_vid_deinit();
+#endif
+
+#if defined(PJMEDIA_HAS_OPENH264_CODEC) && PJMEDIA_HAS_OPENH264_CODEC != 0
+    pjmedia_codec_openh264_vid_deinit();
 #endif
 
