diff --git a/config/T536/gstomx.conf b/config/T536/gstomx.conf
new file mode 100644
index 0000000..de2144b
--- /dev/null
+++ b/config/T536/gstomx.conf
@@ -0,0 +1,26 @@
+[omxmjpegvideodec]
+type-name=GstOMXMJPEGDec
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.mjpeg
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxmjpegvideoenc]
+type-name=GstOMXMJPEGEnc
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.encoder.mjpeg
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;video-framerate-integer;syncframe-flag-not-used;no-disable-outport
+
+[omxh264videoenc]
+type-name=GstOMXH264Enc
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.encoder.avc
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;video-framerate-integer;syncframe-flag-not-used;no-disable-outport
\ No newline at end of file
diff --git a/config/T536/meson.build b/config/T536/meson.build
new file mode 100644
index 0000000..dc99c08
--- /dev/null
+++ b/config/T536/meson.build
@@ -0,0 +1 @@
+install_data (['gstomx.conf'], install_dir : omx_conf_dir)
diff --git a/config/buildroot/gstomx.conf b/config/buildroot/gstomx.conf
new file mode 100644
index 0000000..dfe1670
--- /dev/null
+++ b/config/buildroot/gstomx.conf
@@ -0,0 +1,179 @@
+[omxmpeg2videodec]
+type-name=GstOMXMPEG2VideoDec
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.mpeg2
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxmjpegvideodec]
+type-name=GstOMXMJPEGDec
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.mjpeg
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxmpeg1videodec]
+type-name=GstOMXMPEG1Dec
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.mpeg1
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxmpeg4videodec]
+type-name=GstOMXMPEG4VideoDec
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.mpeg4
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxmsmpeg4v1videodec]
+type-name=GstOMXMSMPEG4V1Dec
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.msmpeg4v1
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxmsmpeg4v2videodec]
+type-name=GstOMXMSMPEG4V2Dec
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.msmpeg4v2
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxmsmpeg4v3videodec]
+type-name=GstOMXMSMPEG4V3Dec
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.msmpeg4v3
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxxvidvideodec]
+type-name=GstOMXXVIDDec
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.xvid
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxflv1videodec]
+type-name=GstOMXFLV1Dec
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.s263
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxh263videodec]
+type-name=GstOMXH263Dec
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.h263
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxh264dec]
+type-name=GstOMXH264Dec
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.avc
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxvp6videodec]
+type-name=GstOMXVP6Dec
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.vp6
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;video-framerate-integer;syncframe-flag-not-used;no-disable-outport
+
+[omxvp8videodec]
+type-name=GstOMXVP8Dec
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.vp8
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;video-framerate-integer;syncframe-flag-not-used;no-disable-outport
+
+[omxvp9videodec]
+type-name=GstOMXVP9Dec
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.vp9
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;video-framerate-integer;syncframe-flag-not-used;no-disable-outport
+
+[omxhevcvideodec]
+type-name=GstOMXH265Dec
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.hevc
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;video-framerate-integer;syncframe-flag-not-used;no-disable-outport
+
+[omxh264videoenc]
+type-name=GstOMXH264Enc
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.encoder.avc
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;video-framerate-integer;syncframe-flag-not-used;no-disable-outport
+
+[omxrxvideodec]
+type-name=GstOMXRXDec
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.rx
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxavsvideodec]
+type-name=GstOMXAVSDec
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.avs
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxh264videoenc]
+type-name=GstOMXH264Enc
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.encoder.avc
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;video-framerate-integer;syncframe-flag-not-used;no-disable-outport
+
+[omxmjpegvideoenc]
+type-name=GstOMXMJPEGEnc
+core-name=/usr/lib/libOmxCore.so
+component-name=OMX.allwinner.video.encoder.mjpeg
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;video-framerate-integer;syncframe-flag-not-used;no-disable-outport
\ No newline at end of file
diff --git a/config/buildroot/meson.build b/config/buildroot/meson.build
new file mode 100644
index 0000000..dc99c08
--- /dev/null
+++ b/config/buildroot/meson.build
@@ -0,0 +1 @@
+install_data (['gstomx.conf'], install_dir : omx_conf_dir)
diff --git a/config/debian/gstomx.conf b/config/debian/gstomx.conf
new file mode 100644
index 0000000..2667c49
--- /dev/null
+++ b/config/debian/gstomx.conf
@@ -0,0 +1,179 @@
+[omxmpeg2videodec]
+type-name=GstOMXMPEG2VideoDec
+core-name=/usr/lib/aarch64-linux-gnu/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.mpeg2
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxmjpegvideodec]
+type-name=GstOMXMJPEGDec
+core-name=/usr/lib/aarch64-linux-gnu/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.mjpeg
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxmpeg1videodec]
+type-name=GstOMXMPEG1Dec
+core-name=/usr/lib/aarch64-linux-gnu/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.mpeg1
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxmpeg4videodec]
+type-name=GstOMXMPEG4VideoDec
+core-name=/usr/lib/aarch64-linux-gnu/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.mpeg4
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxmsmpeg4v1videodec]
+type-name=GstOMXMSMPEG4V1Dec
+core-name=/usr/lib/aarch64-linux-gnu/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.msmpeg4v1
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxmsmpeg4v2videodec]
+type-name=GstOMXMSMPEG4V2Dec
+core-name=/usr/lib/aarch64-linux-gnu/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.msmpeg4v2
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxmsmpeg4v3videodec]
+type-name=GstOMXMSMPEG4V3Dec
+core-name=/usr/lib/aarch64-linux-gnu/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.msmpeg4v3
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxxvidvideodec]
+type-name=GstOMXXVIDDec
+core-name=/usr/lib/aarch64-linux-gnu/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.xvid
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxflv1videodec]
+type-name=GstOMXFLV1Dec
+core-name=/usr/lib/aarch64-linux-gnu/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.s263
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxh263videodec]
+type-name=GstOMXH263Dec
+core-name=/usr/lib/aarch64-linux-gnu/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.h263
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxh264dec]
+type-name=GstOMXH264Dec
+core-name=/usr/lib/aarch64-linux-gnu/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.avc
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxvp6videodec]
+type-name=GstOMXVP6Dec
+core-name=/usr/lib/aarch64-linux-gnu/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.vp6
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;video-framerate-integer;syncframe-flag-not-used;no-disable-outport
+
+[omxvp8videodec]
+type-name=GstOMXVP8Dec
+core-name=/usr/lib/aarch64-linux-gnu/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.vp8
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;video-framerate-integer;syncframe-flag-not-used;no-disable-outport
+
+[omxvp9videodec]
+type-name=GstOMXVP9Dec
+core-name=/usr/lib/aarch64-linux-gnu/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.vp9
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;video-framerate-integer;syncframe-flag-not-used;no-disable-outport
+
+[omxhevcvideodec]
+type-name=GstOMXH265Dec
+core-name=/usr/lib/aarch64-linux-gnu/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.hevc
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;video-framerate-integer;syncframe-flag-not-used;no-disable-outport
+
+[omxh264videoenc]
+type-name=GstOMXH264Enc
+core-name=/usr/lib/aarch64-linux-gnu/libOmxCore.so
+component-name=OMX.allwinner.video.encoder.avc
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;video-framerate-integer;syncframe-flag-not-used;no-disable-outport
+
+[omxrxvideodec]
+type-name=GstOMXRXDec
+core-name=/usr/lib/aarch64-linux-gnu/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.rx
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxavsvideodec]
+type-name=GstOMXAVSDec
+core-name=/usr/lib/aarch64-linux-gnu/libOmxCore.so
+component-name=OMX.allwinner.video.decoder.avs
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;event-port-settings-changed-port-0-to-1;no-disable-outport
+
+[omxh264videoenc]
+type-name=GstOMXH264Enc
+core-name=/usr/lib/aarch64-linux-gnu/libOmxCore.so
+component-name=OMX.allwinner.video.encoder.avc
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;video-framerate-integer;syncframe-flag-not-used;no-disable-outport
+
+[omxmjpegvideoenc]
+type-name=GstOMXMJPEGEnc
+core-name=/usr/lib/aarch64-linux-gnu/libOmxCore.so
+component-name=OMX.allwinner.video.encoder.mjpeg
+rank=257
+in-port-index=0
+out-port-index=1
+hacks=event-port-settings-changed-ndata-parameter-swap;video-framerate-integer;syncframe-flag-not-used;no-disable-outport
\ No newline at end of file
diff --git a/config/meson.build b/config/meson.build
index 1068c6d..67a8ffc 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -1,4 +1,8 @@
-if omx_target == 'rpi'
+if omx_target == 'buildroot'
+  sub = 'buildroot'
+elif omx_target == 'debian'
+  sub = 'debian'
+elif omx_target == 'rpi'
   sub = 'rpi'
 elif omx_target == 'bellagio'
   sub = 'bellagio'
@@ -6,6 +10,8 @@ elif omx_target == 'zynqultrascaleplus'
   sub = 'zynqultrascaleplus'
 elif omx_target == 'tizonia'
   sub = 'tizonia'
+elif omx_target == 'T536'
+  sub = 'T536'
 else
   # No config file defined for the 'generic' target
   sub = ''
diff --git a/meson.build b/meson.build
index 0f1f108..5caee09 100644
--- a/meson.build
+++ b/meson.build
@@ -181,6 +181,44 @@ default_omx_struct_packing = 0
 omx_target = get_option ('target')
 if omx_target == 'generic'
   cdata.set('USE_OMX_TARGET_GENERIC', 1)
+elif omx_target == 'buildroot'
+  default_omx_struct_packing = 4
+
+  if gstgl_dep.found()
+    if gstgl_dep.type_name() == 'pkgconfig'
+      gl_winsys = gstgl_dep.get_variable('gl_winsys').split(' ')
+      gl_platforms = gstgl_dep.get_variable('gl_platforms').split(' ')
+    elif gstgl_dep.type_name() == 'internal'
+      # XXX assume gst-plugins-base was built with dispmanx and egl support
+      gl_winsys = ['dispmanx']
+      gl_platforms = ['egl']
+    else
+      error ('unreachable dependency type')
+    endif
+
+    if not gl_winsys.contains('dispmanx') or not gl_platforms.contains ('egl')
+      gstgl_dep = dependency('', required : false)
+    endif
+  endif
+elif omx_target == 'T536'
+  default_omx_struct_packing = 4
+
+  if gstgl_dep.found()
+    if gstgl_dep.type_name() == 'pkgconfig'
+      gl_winsys = gstgl_dep.get_variable('gl_winsys').split(' ')
+      gl_platforms = gstgl_dep.get_variable('gl_platforms').split(' ')
+    elif gstgl_dep.type_name() == 'internal'
+      # XXX assume gst-plugins-base was built with dispmanx and egl support
+      gl_winsys = ['dispmanx']
+      gl_platforms = ['egl']
+    else
+      error ('unreachable dependency type')
+    endif
+
+    if not gl_winsys.contains('dispmanx') or not gl_platforms.contains ('egl')
+      gstgl_dep = dependency('', required : false)
+    endif
+  endif
 elif omx_target == 'rpi'
   cdata.set('USE_OMX_TARGET_RPI', 1)
   cdata.set('OMX_SKIP64BIT', 1)
@@ -295,6 +333,16 @@ if have_omx_vp8
   cdata.set('HAVE_VP8', 1)
 endif
 
+have_omx_vp9 = cc.has_header_symbol(
+    'OMX_Video.h',
+    'OMX_VIDEO_CodingVP9',
+    prefix : extra_video_headers,
+    args : gst_omx_args,
+    include_directories : [omx_inc])
+if have_omx_vp9
+  cdata.set('HAVE_VP9', 1)
+endif
+
 have_omx_theora = cc.has_header_symbol(
     'OMX_Video.h',
     'OMX_VIDEO_CodingTheora',
diff --git a/meson_options.txt b/meson_options.txt
index e18beb2..3cb0e0a 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -1,7 +1,7 @@
 option('header_path', type : 'string', value : '',
     description : 'An extra include directory to find the OpenMax headers')
 option('target', type : 'combo',
-    choices : ['none', 'generic', 'rpi', 'bellagio', 'tizonia', 'zynqultrascaleplus'], value : 'none',
+    choices : ['none', 'generic', 'cedarx', 'rpi', 'bellagio', 'tizonia', 'zynqultrascaleplus', 'T536', 'buildroot'], value : 'none',
     description : 'The OMX platform to target')
 option('struct_packing', type : 'combo',
     choices : ['0', '1', '2', '4', '8'], value : '0',
diff --git a/omx/gstomx.c b/omx/gstomx.c
index 8aeb99b..83bf711 100644
--- a/omx/gstomx.c
+++ b/omx/gstomx.c
@@ -42,6 +42,7 @@
 #include "gstomxh264enc.h"
 #include "gstomxh263enc.h"
 #include "gstomxh265enc.h"
+#include "gstomxmjpegenc.h"
 #include "gstomxaacdec.h"
 #include "gstomxmp3dec.h"
 #include "gstomxmp3enc.h"
@@ -49,6 +50,11 @@
 #include "gstomxamrdec.h"
 #include "gstomxanalogaudiosink.h"
 #include "gstomxhdmiaudiosink.h"
+#include "gstomxvp9dec.h"
+#include "gstomxavsdec.h"
+#include "gstomxdivxdec.h"
+#include "gstomxdivx4dec.h"
+#include "gstomxmpeg1dec.h"
 
 GST_DEBUG_CATEGORY (gstomx_debug);
 #define GST_CAT_DEFAULT gstomx_debug
@@ -422,6 +428,20 @@ gst_omx_component_handle_messages (GstOMXComponent * comp)
           }
         }
 
+        //AW CODE
+        /* No need to ref input frame because buffer will automatic reference if passed to omx component
+         * and unref it if we have filled the buffer done.
+        if (port->port_def.eDir == OMX_DirInput && buf->omx_buf->pPlatformPrivate)
+        {
+          OmxPrivateBuffer *private = (OmxPrivateBuffer*) buf->omx_buf->pPlatformPrivate;
+          GstBuffer *frame = (GstBuffer *) private->gstFrame;
+          if (frame) {
+            GST_DEBUG_OBJECT(comp->parent ,"Empty Input Buffer Done unref %p", frame);
+            gst_buffer_unref(frame);
+          }
+        }*/
+        //AW END
+
         /* If an input port is managed by a pool, the buffer will be ready to be
          * filled again once it's been released to the pool. */
         if (port->port_def.eDir == OMX_DirOutput || !port->using_pool) {
@@ -3523,7 +3543,9 @@ static const GGetTypeFunction types[] = {
   gst_omx_aac_enc_get_type, gst_omx_mjpeg_dec_get_type,
   gst_omx_aac_dec_get_type, gst_omx_mp3_dec_get_type,
   gst_omx_aac_dec_get_type, gst_omx_mp3_enc_get_type,
-  gst_omx_amr_dec_get_type
+  gst_omx_amr_dec_get_type, gst_omx_divx_dec_get_type,
+  gst_omx_avs_dec_get_type, gst_omx_divx4_dec_get_type,
+  gst_omx_mpeg1_dec_get_type, gst_omx_mjpeg_enc_get_type
 #ifdef HAVE_VP8
       , gst_omx_vp8_dec_get_type
 #endif
@@ -3533,6 +3555,9 @@ static const GGetTypeFunction types[] = {
 #ifdef HAVE_HEVC
       , gst_omx_h265_enc_get_type, gst_omx_h265_dec_get_type
 #endif
+#ifdef HAVE_VP9
+      , gst_omx_vp9_dec_get_type
+#endif
 };
 
 struct TypeOffest
diff --git a/omx/gstomx.c.orig b/omx/gstomx.c.orig
new file mode 100644
index 0000000..8aeb99b
--- /dev/null
+++ b/omx/gstomx.c.orig
@@ -0,0 +1,4179 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ *   Author: Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ * Copyright (C) 2013, Collabora Ltd.
+ *   Author: Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/allocators/gstdmabuf.h>
+#include <string.h>
+
+#include "gstomx.h"
+#include "gstomxmjpegdec.h"
+#include "gstomxmpeg2videodec.h"
+#include "gstomxmpeg4videodec.h"
+#include "gstomxh264dec.h"
+#include "gstomxh263dec.h"
+#include "gstomxh265dec.h"
+#include "gstomxvp8dec.h"
+#include "gstomxtheoradec.h"
+#include "gstomxwmvdec.h"
+#include "gstomxmpeg4videoenc.h"
+#include "gstomxh264enc.h"
+#include "gstomxh263enc.h"
+#include "gstomxh265enc.h"
+#include "gstomxaacdec.h"
+#include "gstomxmp3dec.h"
+#include "gstomxmp3enc.h"
+#include "gstomxaacenc.h"
+#include "gstomxamrdec.h"
+#include "gstomxanalogaudiosink.h"
+#include "gstomxhdmiaudiosink.h"
+
+GST_DEBUG_CATEGORY (gstomx_debug);
+#define GST_CAT_DEFAULT gstomx_debug
+
+GST_DEBUG_CATEGORY_STATIC (OMX_API_TRACE);
+
+/* Macros used to log result of OMX calls. Use the requested debug level if the
+ * operation succeeded and GST_LEVEL_ERROR if not.
+ * Don't consider OMX_ErrorNoMore as an error as it means we're done iterating. */
+#define DEBUG_IF_OK(obj,err,...) \
+  GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, (err == OMX_ErrorNone || err == OMX_ErrorNoMore) ? GST_LEVEL_DEBUG : GST_LEVEL_ERROR, obj, __VA_ARGS__)
+#define INFO_IF_OK(obj,err,...) \
+  GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, (err == OMX_ErrorNone || err == OMX_ErrorNoMore) ? GST_LEVEL_INFO : GST_LEVEL_ERROR, obj, __VA_ARGS__)
+
+G_LOCK_DEFINE_STATIC (core_handles);
+static GHashTable *core_handles;
+
+/* Cache used by gst_omx_buffer_flags_to_string() */
+G_LOCK_DEFINE_STATIC (buffer_flags_str);
+static GHashTable *buffer_flags_str;
+
+GstOMXCore *
+gst_omx_core_acquire (const gchar * filename)
+{
+  GstOMXCore *core;
+
+  G_LOCK (core_handles);
+  if (!core_handles)
+    core_handles =
+        g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+  core = g_hash_table_lookup (core_handles, filename);
+  if (!core) {
+    core = g_slice_new0 (GstOMXCore);
+    g_mutex_init (&core->lock);
+    core->user_count = 0;
+    g_hash_table_insert (core_handles, g_strdup (filename), core);
+
+    /* Hack for the Broadcom OpenMAX IL implementation */
+#ifdef USE_OMX_TARGET_RPI
+    {
+#else
+    if (g_str_has_suffix (filename, "vc/lib/libopenmaxil.so")) {
+#endif
+      gchar *bcm_host_filename;
+      gchar *bcm_host_path;
+      GModule *bcm_host_module;
+      void (*bcm_host_init) (void);
+
+      bcm_host_path = g_path_get_dirname (filename);
+      bcm_host_filename =
+          g_build_filename (bcm_host_path, "libbcm_host.so", NULL);
+
+      bcm_host_module =
+          g_module_open (bcm_host_filename,
+          G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+
+      g_free (bcm_host_filename);
+      g_free (bcm_host_path);
+
+      if (!bcm_host_module) {
+        /* Retry without an absolute path */
+        bcm_host_module =
+            g_module_open ("libbcm_host.so",
+            G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+        if (!bcm_host_module) {
+          GST_ERROR ("Failed to load libbcm_host.so");
+          goto error;
+        }
+      }
+
+      if (!g_module_symbol (bcm_host_module, "bcm_host_init",
+              (gpointer *) & bcm_host_init)) {
+        GST_ERROR ("Failed to load symbol 'bcm_host_init' from libbcm_host.so");
+        goto error;
+      }
+
+      bcm_host_init ();
+    }
+
+    core->module =
+        g_module_open (filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+    if (!core->module)
+      goto load_failed;
+
+    if (!g_module_symbol (core->module, "OMX_Init", (gpointer *) & core->init))
+      goto symbol_error;
+    if (!g_module_symbol (core->module, "OMX_Deinit",
+            (gpointer *) & core->deinit))
+      goto symbol_error;
+    if (!g_module_symbol (core->module, "OMX_GetHandle",
+            (gpointer *) & core->get_handle))
+      goto symbol_error;
+    if (!g_module_symbol (core->module, "OMX_FreeHandle",
+            (gpointer *) & core->free_handle))
+      goto symbol_error;
+    if (!g_module_symbol (core->module, "OMX_SetupTunnel",
+            (gpointer *) & core->setup_tunnel))
+      goto symbol_error;
+
+    GST_DEBUG ("Successfully loaded core '%s'", filename);
+  }
+
+  g_mutex_lock (&core->lock);
+  core->user_count++;
+  if (core->user_count == 1) {
+    OMX_ERRORTYPE err;
+
+    err = core->init ();
+    if (err != OMX_ErrorNone) {
+      GST_ERROR ("Failed to initialize core '%s': 0x%08x", filename, err);
+      g_mutex_unlock (&core->lock);
+      goto error;
+    }
+
+    GST_DEBUG ("Successfully initialized core '%s'", filename);
+  }
+
+  g_mutex_unlock (&core->lock);
+  G_UNLOCK (core_handles);
+
+  return core;
+
+load_failed:
+  {
+    GST_ERROR ("Failed to load module '%s': %s", filename, g_module_error ());
+    goto error;
+  }
+symbol_error:
+  {
+    GST_ERROR ("Failed to locate required OpenMAX symbol in '%s': %s", filename,
+        g_module_error ());
+    g_module_close (core->module);
+    core->module = NULL;
+    goto error;
+  }
+error:
+  {
+    g_hash_table_remove (core_handles, filename);
+    g_mutex_clear (&core->lock);
+    g_slice_free (GstOMXCore, core);
+
+    G_UNLOCK (core_handles);
+
+    return NULL;
+  }
+}
+
+void
+gst_omx_core_release (GstOMXCore * core)
+{
+  g_return_if_fail (core != NULL);
+
+  G_LOCK (core_handles);
+
+  g_mutex_lock (&core->lock);
+
+  GST_DEBUG ("Releasing core %p", core);
+
+  core->user_count--;
+  if (core->user_count == 0) {
+    GST_DEBUG ("Deinit core %p", core);
+    core->deinit ();
+
+    G_LOCK (buffer_flags_str);
+    g_clear_pointer (&buffer_flags_str, g_hash_table_unref);
+    G_UNLOCK (buffer_flags_str);
+  }
+
+  g_mutex_unlock (&core->lock);
+
+  G_UNLOCK (core_handles);
+}
+
+/* NOTE: comp->messages_lock will be used */
+static void
+gst_omx_component_flush_messages (GstOMXComponent * comp)
+{
+  GstOMXMessage *msg;
+
+  g_mutex_lock (&comp->messages_lock);
+  while ((msg = g_queue_pop_head (&comp->messages))) {
+    g_slice_free (GstOMXMessage, msg);
+  }
+  g_mutex_unlock (&comp->messages_lock);
+}
+
+static void
+gst_omx_buffer_reset (GstOMXBuffer * buf)
+{
+  buf->omx_buf->nFlags = 0;
+  buf->omx_buf->nOffset = 0;
+  buf->omx_buf->nFilledLen = 0;
+  GST_OMX_SET_TICKS (buf->omx_buf->nTimeStamp, G_GUINT64_CONSTANT (0));
+}
+
+static void gst_omx_buffer_unmap (GstOMXBuffer * buffer);
+
+/* NOTE: Call with comp->lock, comp->messages_lock will be used */
+static void
+gst_omx_component_handle_messages (GstOMXComponent * comp)
+{
+  GstOMXMessage *msg;
+
+  g_mutex_lock (&comp->messages_lock);
+  while ((msg = g_queue_pop_head (&comp->messages))) {
+    g_mutex_unlock (&comp->messages_lock);
+
+    switch (msg->type) {
+      case GST_OMX_MESSAGE_STATE_SET:{
+        GST_INFO_OBJECT (comp->parent, "%s state change to %s finished",
+            comp->name, gst_omx_state_to_string (msg->content.state_set.state));
+        comp->state = msg->content.state_set.state;
+        if (comp->state == comp->pending_state)
+          comp->pending_state = OMX_StateInvalid;
+        break;
+      }
+      case GST_OMX_MESSAGE_FLUSH:{
+        GstOMXPort *port = NULL;
+        OMX_U32 index = msg->content.flush.port;
+
+        port = gst_omx_component_get_port (comp, index);
+        if (!port)
+          break;
+
+        GST_DEBUG_OBJECT (comp->parent, "%s port %u flushed", comp->name,
+            port->index);
+
+        if (port->flushing) {
+          port->flushed = TRUE;
+        } else {
+          GST_ERROR_OBJECT (comp->parent, "%s port %u was not flushing",
+              comp->name, port->index);
+        }
+
+        break;
+      }
+      case GST_OMX_MESSAGE_ERROR:{
+        OMX_ERRORTYPE error = msg->content.error.error;
+
+        if (error == OMX_ErrorNone)
+          break;
+
+        GST_ERROR_OBJECT (comp->parent, "%s got error: %s (0x%08x)", comp->name,
+            gst_omx_error_to_string (error), error);
+
+        /* We only set the first error ever from which
+         * we can't recover anymore.
+         */
+        if (comp->last_error == OMX_ErrorNone)
+          comp->last_error = error;
+        g_cond_broadcast (&comp->messages_cond);
+
+        break;
+      }
+      case GST_OMX_MESSAGE_PORT_ENABLE:{
+        GstOMXPort *port = NULL;
+        OMX_U32 index = msg->content.port_enable.port;
+        OMX_BOOL enable = msg->content.port_enable.enable;
+
+        port = gst_omx_component_get_port (comp, index);
+        if (!port)
+          break;
+
+        GST_DEBUG_OBJECT (comp->parent, "%s port %u %s", comp->name,
+            port->index, (enable ? "enabled" : "disabled"));
+
+        if (enable)
+          port->enabled_pending = FALSE;
+        else
+          port->disabled_pending = FALSE;
+        break;
+      }
+      case GST_OMX_MESSAGE_PORT_SETTINGS_CHANGED:{
+        gint i, n;
+        OMX_U32 index = msg->content.port_settings_changed.port;
+        GList *outports = NULL, *l, *k;
+
+        GST_DEBUG_OBJECT (comp->parent, "%s settings changed (port %u)",
+            comp->name, (guint) index);
+
+        /* FIXME: This probably can be done better */
+
+        /* Now update the ports' states */
+        n = (comp->ports ? comp->ports->len : 0);
+        for (i = 0; i < n; i++) {
+          GstOMXPort *port = g_ptr_array_index (comp->ports, i);
+
+          if (index == OMX_ALL || index == port->index) {
+            port->settings_cookie++;
+            gst_omx_port_update_port_definition (port, NULL);
+            if (port->port_def.eDir == OMX_DirOutput && !port->tunneled)
+              outports = g_list_prepend (outports, port);
+          }
+        }
+
+        for (k = outports; k; k = k->next) {
+          gboolean found = FALSE;
+
+          for (l = comp->pending_reconfigure_outports; l; l = l->next) {
+            if (l->data == k->data) {
+              found = TRUE;
+              break;
+            }
+          }
+
+          if (!found)
+            comp->pending_reconfigure_outports =
+                g_list_prepend (comp->pending_reconfigure_outports, k->data);
+        }
+
+        g_list_free (outports);
+
+        break;
+      }
+      case GST_OMX_MESSAGE_BUFFER_FLAG:{
+        GstOMXPort *port = NULL;
+        OMX_U32 index = msg->content.buffer_flag.port;
+        OMX_U32 flags = msg->content.buffer_flag.flags;
+
+        port = gst_omx_component_get_port (comp, index);
+        if (!port)
+          break;
+
+        GST_DEBUG_OBJECT (comp->parent,
+            "%s port %u got buffer flags 0x%08x (%s)", comp->name, port->index,
+            (guint) flags, gst_omx_buffer_flags_to_string (flags));
+        if ((flags & OMX_BUFFERFLAG_EOS)
+            && port->port_def.eDir == OMX_DirOutput && !port->eos) {
+          GST_DEBUG_OBJECT (comp->parent, "%s port %u is EOS", comp->name,
+              port->index);
+          port->eos = TRUE;
+        }
+
+        break;
+      }
+      case GST_OMX_MESSAGE_BUFFER_DONE:{
+        GstOMXBuffer *buf = msg->content.buffer_done.buffer->pAppPrivate;
+        GstOMXPort *port;
+
+        port = buf->port;
+
+        buf->used = FALSE;
+
+        if (msg->content.buffer_done.empty) {
+          /* Input buffer is empty again and can be used to contain new input */
+          GST_LOG_OBJECT (port->comp->parent,
+              "%s port %u emptied buffer %p (%p)", port->comp->name,
+              port->index, buf, buf->omx_buf->pBuffer);
+
+          /* Reset all flags, some implementations don't
+           * reset them themselves and the flags are not
+           * valid anymore after the buffer was consumed
+           */
+          gst_omx_buffer_reset (buf);
+
+          /* Release and unmap the parent buffer, if any */
+          gst_omx_buffer_unmap (buf);
+        } else {
+          /* Output buffer contains output now or
+           * the port was flushed */
+          GST_LOG_OBJECT (port->comp->parent,
+              "%s port %u filled buffer %p (%p)", port->comp->name, port->index,
+              buf, buf->omx_buf->pBuffer);
+
+          if ((buf->omx_buf->nFlags & OMX_BUFFERFLAG_EOS)
+              && port->port_def.eDir == OMX_DirOutput && !port->eos) {
+            GST_DEBUG_OBJECT (comp->parent, "%s port %u is EOS", comp->name,
+                port->index);
+            port->eos = TRUE;
+          }
+        }
+
+        /* If an input port is managed by a pool, the buffer will be ready to be
+         * filled again once it's been released to the pool. */
+        if (port->port_def.eDir == OMX_DirOutput || !port->using_pool) {
+          g_queue_push_tail (&port->pending_buffers, buf);
+        }
+
+        break;
+      }
+      default:{
+        g_assert_not_reached ();
+        break;
+      }
+    }
+
+    g_slice_free (GstOMXMessage, msg);
+
+    g_mutex_lock (&comp->messages_lock);
+  }
+
+  g_mutex_unlock (&comp->messages_lock);
+}
+
+/* NOTE: comp->messages_lock will be used */
+static void
+gst_omx_component_send_message (GstOMXComponent * comp, GstOMXMessage * msg)
+{
+  g_mutex_lock (&comp->messages_lock);
+  if (msg)
+    g_queue_push_tail (&comp->messages, msg);
+  g_cond_broadcast (&comp->messages_cond);
+  g_mutex_unlock (&comp->messages_lock);
+}
+
+/* NOTE: Call with comp->lock, comp->messages_lock will be used */
+static gboolean
+gst_omx_component_wait_message (GstOMXComponent * comp, GstClockTime timeout)
+{
+  gboolean signalled;
+  gint64 wait_until = -1;
+
+  if (timeout != GST_CLOCK_TIME_NONE) {
+    gint64 add = timeout / (GST_SECOND / G_TIME_SPAN_SECOND);
+
+    if (add == 0)
+      return FALSE;
+
+    wait_until = g_get_monotonic_time () + add;
+    GST_DEBUG_OBJECT (comp->parent, "%s waiting for %" G_GINT64_FORMAT "us",
+        comp->name, add);
+  } else {
+    GST_DEBUG_OBJECT (comp->parent, "%s waiting for signal", comp->name);
+  }
+
+  g_mutex_lock (&comp->messages_lock);
+  g_mutex_unlock (&comp->lock);
+
+  if (!g_queue_is_empty (&comp->messages)) {
+    signalled = TRUE;
+  } else if (timeout == GST_CLOCK_TIME_NONE) {
+    g_cond_wait (&comp->messages_cond, &comp->messages_lock);
+    signalled = TRUE;
+  } else {
+    signalled =
+        g_cond_wait_until (&comp->messages_cond, &comp->messages_lock,
+        wait_until);
+  }
+
+  g_mutex_unlock (&comp->messages_lock);
+  g_mutex_lock (&comp->lock);
+
+  return signalled;
+}
+
+static const gchar *
+omx_event_type_to_str (OMX_EVENTTYPE event)
+{
+  switch (event) {
+    case OMX_EventCmdComplete:
+      return "EventCmdComplete";
+    case OMX_EventError:
+      return "EventError";
+    case OMX_EventMark:
+      return "EventMark";
+    case OMX_EventPortSettingsChanged:
+      return "EventPortSettingsChanged";
+    case OMX_EventBufferFlag:
+      return "EventBufferFlag";
+    case OMX_EventResourcesAcquired:
+      return "EventResourcesAcquired";
+    case OMX_EventComponentResumed:
+      return "EventComponentResumed";
+    case OMX_EventDynamicResourcesAvailable:
+      return "EventDynamicResourcesAvailable";
+    case OMX_EventPortFormatDetected:
+      return "EventPortFormatDetected";
+#ifdef OMX_EventIndexSettingChanged
+    case OMX_EventIndexSettingChanged:
+      return "EventIndexSettingChanged";
+#endif
+#ifdef OMX_EventPortNeedsDisable
+    case OMX_EventPortNeedsDisable:
+      return "EventPortNeedsDisable";
+#endif
+#ifdef OMX_EventPortNeedsFlush
+    case OMX_EventPortNeedsFlush:
+      return "EventPortNeedsFlush";
+#endif
+    case OMX_EventKhronosExtensions:
+    case OMX_EventVendorStartUnused:
+    case OMX_EventMax:
+    default:
+      break;
+  }
+
+  return NULL;
+}
+
+/* See "Table 3-11: Event Parameter Usage" */
+static GstStructure *
+omx_event_to_debug_struct (OMX_EVENTTYPE event,
+    guint32 data1, guint32 data2, gpointer event_data)
+{
+  const gchar *name;
+
+  name = omx_event_type_to_str (event);
+  switch (event) {
+    case OMX_EventCmdComplete:
+    {
+      const gchar *cmd = gst_omx_command_to_string (data1);
+
+      if (!cmd)
+        break;
+
+      switch (data1) {
+        case OMX_CommandStateSet:
+          return gst_structure_new (name,
+              "command", G_TYPE_STRING, cmd,
+              "state-reached", G_TYPE_STRING, gst_omx_state_to_string (data2),
+              NULL);
+        case OMX_CommandFlush:
+        case OMX_CommandPortDisable:
+        case OMX_CommandPortEnable:
+        case OMX_CommandMarkBuffer:
+          return gst_structure_new (name,
+              "command", G_TYPE_STRING, cmd, "port", G_TYPE_UINT, data2,
+              "error", G_TYPE_STRING,
+              gst_omx_error_to_string (GPOINTER_TO_UINT (event_data)), NULL);
+        case OMX_CommandKhronosExtensions:
+        case OMX_CommandVendorStartUnused:
+        case OMX_CommandMax:
+          break;
+      }
+    }
+      break;
+    case OMX_EventError:
+      return gst_structure_new (name, "error", G_TYPE_STRING,
+          gst_omx_error_to_string (data1), "extra-info", G_TYPE_STRING,
+          gst_omx_error_to_string (data2), NULL);
+    case OMX_EventMark:
+    case OMX_EventComponentResumed:
+    case OMX_EventResourcesAcquired:
+    case OMX_EventDynamicResourcesAvailable:
+    case OMX_EventPortFormatDetected:
+      return gst_structure_new_empty (name);
+    case OMX_EventPortSettingsChanged:
+#ifdef OMX_EventIndexSettingChanged
+    case OMX_EventIndexSettingChanged:
+#endif
+#ifdef OMX_EventPortNeedsDisable
+    case OMX_EventPortNeedsDisable:
+#endif
+#ifdef OMX_EventPortNeedsFlush
+    case OMX_EventPortNeedsFlush:
+#endif
+      return gst_structure_new (name, "port", G_TYPE_UINT,
+          data1, "param-config", G_TYPE_UINT, data2, NULL);
+    case OMX_EventBufferFlag:
+      return gst_structure_new (name, "port", G_TYPE_UINT,
+          data1, "flags", G_TYPE_STRING, gst_omx_buffer_flags_to_string (data2),
+          NULL);
+    case OMX_EventKhronosExtensions:
+    case OMX_EventVendorStartUnused:
+    case OMX_EventMax:
+    default:
+      break;
+  }
+
+  return NULL;
+}
+
+static void
+log_omx_api_trace_event (GstOMXComponent * comp, OMX_EVENTTYPE event,
+    guint32 data1, guint32 data2, gpointer event_data)
+{
+#ifndef GST_DISABLE_GST_DEBUG
+  GstStructure *s;
+
+  /* Don't bother creating useless structs if not needed */
+  if (gst_debug_category_get_threshold (OMX_API_TRACE) < GST_LEVEL_DEBUG)
+    return;
+
+  s = omx_event_to_debug_struct (event, data1, data2, event_data);
+  if (!s) {
+    GST_CAT_WARNING_OBJECT (OMX_API_TRACE, comp->parent,
+        "invalid event 0x%08x Data1 %u Data2 %u EventData %p", event, data1,
+        data2, event_data);
+    return;
+  }
+
+  GST_CAT_DEBUG_OBJECT (OMX_API_TRACE, comp->parent, "%" GST_PTR_FORMAT, s);
+
+  gst_structure_free (s);
+#endif /* GST_DISABLE_GST_DEBUG */
+}
+
+static OMX_ERRORTYPE
+EventHandler (OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_EVENTTYPE eEvent,
+    OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData)
+{
+  GstOMXComponent *comp = (GstOMXComponent *) pAppData;
+
+  log_omx_api_trace_event (comp, eEvent, nData1, nData2, pEventData);
+
+  switch (eEvent) {
+    case OMX_EventCmdComplete:
+    {
+      OMX_COMMANDTYPE cmd = (OMX_COMMANDTYPE) nData1;
+
+      GST_DEBUG_OBJECT (comp->parent, "%s %s command complete (%d)",
+          comp->name, gst_omx_command_to_string (cmd), cmd);
+
+      switch (cmd) {
+        case OMX_CommandStateSet:{
+          GstOMXMessage *msg = g_slice_new (GstOMXMessage);
+
+          msg->type = GST_OMX_MESSAGE_STATE_SET;
+          msg->content.state_set.state = nData2;
+
+          GST_DEBUG_OBJECT (comp->parent, "%s state change to %s finished",
+              comp->name,
+              gst_omx_state_to_string (msg->content.state_set.state));
+
+          gst_omx_component_send_message (comp, msg);
+          break;
+        }
+        case OMX_CommandFlush:{
+          GstOMXMessage *msg = g_slice_new (GstOMXMessage);
+
+          msg->type = GST_OMX_MESSAGE_FLUSH;
+          msg->content.flush.port = nData2;
+          GST_DEBUG_OBJECT (comp->parent, "%s port %u flushed", comp->name,
+              (guint) msg->content.flush.port);
+
+          gst_omx_component_send_message (comp, msg);
+          break;
+        }
+        case OMX_CommandPortEnable:
+        case OMX_CommandPortDisable:{
+          GstOMXMessage *msg = g_slice_new (GstOMXMessage);
+
+          msg->type = GST_OMX_MESSAGE_PORT_ENABLE;
+          msg->content.port_enable.port = nData2;
+          msg->content.port_enable.enable = (cmd == OMX_CommandPortEnable);
+          GST_DEBUG_OBJECT (comp->parent, "%s port %u %s", comp->name,
+              (guint) msg->content.port_enable.port,
+              (msg->content.port_enable.enable ? "enabled" : "disabled"));
+
+          gst_omx_component_send_message (comp, msg);
+          break;
+        }
+        default:
+          break;
+      }
+      break;
+    }
+    case OMX_EventError:
+    {
+      GstOMXMessage *msg;
+      OMX_ERRORTYPE error_type = nData1;
+
+      /* Yes, this really happens... */
+      if (error_type == OMX_ErrorNone)
+        break;
+
+      /* Always ignore PortUnpopulated error. This error is informational
+       * at best but it is useful for debugging some strange scenarios.
+       */
+      if (error_type == OMX_ErrorPortUnpopulated) {
+        GST_DEBUG_OBJECT (comp->parent, "%s got error: %s (0x%08x)",
+            comp->name, gst_omx_error_to_string (error_type), error_type);
+        break;
+      }
+
+      msg = g_slice_new (GstOMXMessage);
+
+      msg->type = GST_OMX_MESSAGE_ERROR;
+      msg->content.error.error = error_type;
+      GST_ERROR_OBJECT (comp->parent, "%s got error: %s (0x%08x)", comp->name,
+          gst_omx_error_to_string (msg->content.error.error),
+          msg->content.error.error);
+
+      gst_omx_component_send_message (comp, msg);
+      break;
+    }
+    case OMX_EventPortSettingsChanged:
+    {
+      GstOMXMessage *msg = g_slice_new (GstOMXMessage);
+      OMX_U32 index;
+
+      if (!(comp->hacks &
+              GST_OMX_HACK_EVENT_PORT_SETTINGS_CHANGED_NDATA_PARAMETER_SWAP)) {
+        index = nData1;
+      } else {
+        index = nData2;
+      }
+
+
+      if (index == 0
+          && (comp->hacks &
+              GST_OMX_HACK_EVENT_PORT_SETTINGS_CHANGED_PORT_0_TO_1))
+        index = 1;
+
+
+      msg->type = GST_OMX_MESSAGE_PORT_SETTINGS_CHANGED;
+      msg->content.port_settings_changed.port = index;
+      GST_DEBUG_OBJECT (comp->parent, "%s settings changed (port index: %u)",
+          comp->name, (guint) msg->content.port_settings_changed.port);
+
+      gst_omx_component_send_message (comp, msg);
+      break;
+    }
+    case OMX_EventBufferFlag:{
+      GstOMXMessage *msg;
+
+      msg = g_slice_new (GstOMXMessage);
+
+      msg->type = GST_OMX_MESSAGE_BUFFER_FLAG;
+      msg->content.buffer_flag.port = nData1;
+      msg->content.buffer_flag.flags = nData2;
+      GST_DEBUG_OBJECT (comp->parent, "%s port %u got buffer flags 0x%08x (%s)",
+          comp->name, (guint) msg->content.buffer_flag.port,
+          (guint) msg->content.buffer_flag.flags,
+          gst_omx_buffer_flags_to_string (msg->content.buffer_flag.flags));
+
+      gst_omx_component_send_message (comp, msg);
+      break;
+    }
+    case OMX_EventPortFormatDetected:
+    default:
+      GST_DEBUG_OBJECT (comp->parent, "%s unknown event 0x%08x", comp->name,
+          eEvent);
+      break;
+  }
+
+  return OMX_ErrorNone;
+}
+
+static void
+gst_omx_buffer_unmap (GstOMXBuffer * buffer)
+{
+  g_return_if_fail (buffer != NULL);
+
+  if (buffer->input_frame_mapped) {
+    g_assert (!buffer->input_mem);
+    g_assert (!buffer->input_buffer);
+    g_assert (!buffer->input_buffer_mapped);
+    gst_video_frame_unmap (&buffer->input_frame);
+    buffer->input_frame_mapped = FALSE;
+  } else if (buffer->input_mem) {
+    g_assert (!buffer->input_buffer);
+    g_assert (!buffer->input_buffer_mapped);
+    gst_memory_unmap (buffer->input_mem, &buffer->map);
+    g_clear_pointer (&buffer->input_mem, gst_memory_unref);
+  } else if (buffer->input_buffer) {
+    if (buffer->input_buffer_mapped)
+      gst_buffer_unmap (buffer->input_buffer, &buffer->map);
+    buffer->input_buffer_mapped = FALSE;
+    g_clear_pointer (&buffer->input_buffer, gst_buffer_unref);
+  }
+}
+
+static void
+log_omx_api_trace_buffer (GstOMXComponent * comp, const gchar * event,
+    GstOMXBuffer * buf)
+{
+#ifndef GST_DISABLE_GST_DEBUG
+  GstStructure *s;
+
+  /* Don't bother creating useless structs if not needed */
+  if (gst_debug_category_get_threshold (OMX_API_TRACE) < GST_LEVEL_TRACE)
+    return;
+
+  if (buf) {
+    gchar *buf_str, *omx_buf_str, *pbuffer_str;
+
+    /* GST_PTR_FORMAT won't serialize G_TYPE_POINTER fields so stringify pointers */
+    buf_str = g_strdup_printf ("%p", buf);
+    omx_buf_str = g_strdup_printf ("%p", buf->omx_buf);
+    pbuffer_str = g_strdup_printf ("%p", buf->omx_buf->pBuffer);
+
+    /* *INDENT-OFF* */
+    s = gst_structure_new (event,
+        "GstOMXBuffer", G_TYPE_STRING, buf_str,
+        "OMX-buffer", G_TYPE_STRING, omx_buf_str,
+        "pBuffer", G_TYPE_STRING, pbuffer_str,
+        "TimeStamp", G_TYPE_UINT64, GST_OMX_GET_TICKS (buf->omx_buf->nTimeStamp),
+        "AllocLen", G_TYPE_UINT, buf->omx_buf->nAllocLen,
+        "FilledLen", G_TYPE_UINT, buf->omx_buf->nFilledLen,
+        "flags", G_TYPE_UINT, buf->omx_buf->nFlags,
+        "flags-str", G_TYPE_STRING, gst_omx_buffer_flags_to_string (buf->omx_buf->nFlags),
+        NULL);
+    /* *INDENT-ON* */
+
+    g_free (buf_str);
+    g_free (omx_buf_str);
+    g_free (pbuffer_str);
+  } else {
+    s = gst_structure_new_empty (event);
+  }
+
+  GST_CAT_TRACE_OBJECT (OMX_API_TRACE, comp->parent, "%" GST_PTR_FORMAT, s);
+
+  gst_structure_free (s);
+#endif /* GST_DISABLE_GST_DEBUG */
+}
+
+static OMX_ERRORTYPE
+EmptyBufferDone (OMX_HANDLETYPE hComponent, OMX_PTR pAppData,
+    OMX_BUFFERHEADERTYPE * pBuffer)
+{
+  GstOMXBuffer *buf;
+  GstOMXComponent *comp;
+  GstOMXMessage *msg;
+
+  buf = pBuffer->pAppPrivate;
+  if (!buf) {
+    GST_ERROR ("Have unknown or deallocated buffer %p", pBuffer);
+    return OMX_ErrorNone;
+  }
+
+  g_assert (buf->omx_buf == pBuffer);
+
+  if (buf->port->tunneled) {
+    GST_ERROR ("EmptyBufferDone on tunneled port");
+    return OMX_ErrorBadParameter;
+  }
+
+  comp = buf->port->comp;
+
+  msg = g_slice_new (GstOMXMessage);
+  msg->type = GST_OMX_MESSAGE_BUFFER_DONE;
+  msg->content.buffer_done.component = hComponent;
+  msg->content.buffer_done.app_data = pAppData;
+  msg->content.buffer_done.buffer = pBuffer;
+  msg->content.buffer_done.empty = OMX_TRUE;
+
+  log_omx_api_trace_buffer (comp, "EmptyBufferDone", buf);
+  GST_LOG_OBJECT (comp->parent, "%s port %u emptied buffer %p (%p)",
+      comp->name, buf->port->index, buf, buf->omx_buf->pBuffer);
+
+  gst_omx_component_send_message (comp, msg);
+
+  return OMX_ErrorNone;
+}
+
+static OMX_ERRORTYPE
+FillBufferDone (OMX_HANDLETYPE hComponent, OMX_PTR pAppData,
+    OMX_BUFFERHEADERTYPE * pBuffer)
+{
+  GstOMXBuffer *buf;
+  GstOMXComponent *comp;
+  GstOMXMessage *msg;
+
+  buf = pBuffer->pAppPrivate;
+  if (!buf) {
+    GST_ERROR ("Have unknown or deallocated buffer %p", pBuffer);
+    return OMX_ErrorNone;
+  }
+
+  g_assert (buf->omx_buf == pBuffer);
+
+  if (buf->port->tunneled) {
+    GST_ERROR ("FillBufferDone on tunneled port");
+    return OMX_ErrorBadParameter;
+  }
+
+  comp = buf->port->comp;
+
+  msg = g_slice_new (GstOMXMessage);
+  msg->type = GST_OMX_MESSAGE_BUFFER_DONE;
+  msg->content.buffer_done.component = hComponent;
+  msg->content.buffer_done.app_data = pAppData;
+  msg->content.buffer_done.buffer = pBuffer;
+  msg->content.buffer_done.empty = OMX_FALSE;
+
+  log_omx_api_trace_buffer (comp, "FillBufferDone", buf);
+  GST_LOG_OBJECT (comp->parent, "%s port %u filled buffer %p (%p)", comp->name,
+      buf->port->index, buf, buf->omx_buf->pBuffer);
+
+  gst_omx_component_send_message (comp, msg);
+
+  return OMX_ErrorNone;
+}
+
+static OMX_CALLBACKTYPE callbacks =
+    { EventHandler, EmptyBufferDone, FillBufferDone };
+
+GST_DEFINE_MINI_OBJECT_TYPE (GstOMXComponent, gst_omx_component);
+
+static void gst_omx_component_free (GstOMXComponent * comp);
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+GstOMXComponent *
+gst_omx_component_new (GstObject * parent, const gchar * core_name,
+    const gchar * component_name, const gchar * component_role, guint64 hacks)
+{
+  OMX_ERRORTYPE err;
+  GstOMXCore *core;
+  GstOMXComponent *comp;
+  const gchar *dot;
+
+  core = gst_omx_core_acquire (core_name);
+  if (!core)
+    return NULL;
+
+  comp = g_slice_new0 (GstOMXComponent);
+  comp->core = core;
+
+  gst_mini_object_init (GST_MINI_OBJECT_CAST (comp), 0,
+      gst_omx_component_get_type (), NULL, NULL,
+      (GstMiniObjectFreeFunction) gst_omx_component_free);
+
+  if ((dot = g_strrstr (component_name, ".")))
+    comp->name = g_strdup (dot + 1);
+  else
+    comp->name = g_strdup (component_name);
+
+  err =
+      core->get_handle (&comp->handle, (OMX_STRING) component_name, comp,
+      &callbacks);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (parent,
+        "Failed to get component handle '%s' from core '%s': 0x%08x",
+        component_name, core_name, err);
+    gst_omx_core_release (core);
+    g_free (comp->name);
+    g_slice_free (GstOMXComponent, comp);
+    return NULL;
+  }
+  GST_DEBUG_OBJECT (parent,
+      "Successfully got component handle %p (%s) from core '%s'", comp->handle,
+      component_name, core_name);
+  comp->parent = gst_object_ref (parent);
+  comp->hacks = hacks;
+
+  comp->ports = g_ptr_array_new ();
+  comp->n_in_ports = 0;
+  comp->n_out_ports = 0;
+
+  g_mutex_init (&comp->lock);
+  g_mutex_init (&comp->messages_lock);
+  g_cond_init (&comp->messages_cond);
+
+  g_queue_init (&comp->messages);
+  comp->pending_state = OMX_StateInvalid;
+  comp->last_error = OMX_ErrorNone;
+
+  /* Set component role if any */
+  if (component_role && !(hacks & GST_OMX_HACK_NO_COMPONENT_ROLE)) {
+    OMX_PARAM_COMPONENTROLETYPE param;
+
+    GST_OMX_INIT_STRUCT (&param);
+
+    g_strlcpy ((gchar *) param.cRole, component_role, sizeof (param.cRole));
+    err =
+        gst_omx_component_set_parameter (comp,
+        OMX_IndexParamStandardComponentRole, &param);
+
+    DEBUG_IF_OK (comp->parent, err,
+        "Setting component role to '%s': %s (0x%08x)", component_role,
+        gst_omx_error_to_string (err), err);
+
+    /* If setting the role failed this component is unusable */
+    if (err != OMX_ErrorNone) {
+      gst_omx_component_free (comp);
+      return NULL;
+    }
+  }
+
+  OMX_GetState (comp->handle, &comp->state);
+
+  g_mutex_lock (&comp->lock);
+  gst_omx_component_handle_messages (comp);
+  g_mutex_unlock (&comp->lock);
+
+  return comp;
+}
+
+/* NOTE: Uses comp->messages_lock */
+static void
+gst_omx_component_free (GstOMXComponent * comp)
+{
+  gint i, n;
+
+  g_return_if_fail (comp != NULL);
+
+  GST_INFO_OBJECT (comp->parent, "Unloading component %p %s", comp, comp->name);
+
+  if (comp->ports) {
+    n = comp->ports->len;
+    for (i = 0; i < n; i++) {
+      GstOMXPort *port = g_ptr_array_index (comp->ports, i);
+
+      gst_omx_port_deallocate_buffers (port);
+      g_assert (port->buffers == NULL);
+      g_assert (g_queue_get_length (&port->pending_buffers) == 0);
+
+      g_slice_free (GstOMXPort, port);
+    }
+    g_ptr_array_unref (comp->ports);
+    comp->ports = NULL;
+  }
+
+  comp->core->free_handle (comp->handle);
+  gst_omx_core_release (comp->core);
+
+  gst_omx_component_flush_messages (comp);
+
+  g_cond_clear (&comp->messages_cond);
+  g_mutex_clear (&comp->messages_lock);
+  g_mutex_clear (&comp->lock);
+
+  gst_object_unref (comp->parent);
+
+  g_free (comp->name);
+  comp->name = NULL;
+
+  g_slice_free (GstOMXComponent, comp);
+}
+
+GstOMXComponent *
+gst_omx_component_ref (GstOMXComponent * comp)
+{
+  g_return_val_if_fail (comp, NULL);
+
+  gst_mini_object_ref (GST_MINI_OBJECT_CAST (comp));
+  return comp;
+}
+
+void
+gst_omx_component_unref (GstOMXComponent * comp)
+{
+  g_return_if_fail (comp);
+
+  gst_mini_object_unref (GST_MINI_OBJECT_CAST (comp));
+}
+
+static GstStructure *
+omx_command_to_debug_struct (OMX_COMMANDTYPE cmd,
+    guint32 param, gpointer cmd_data)
+{
+  const gchar *cmd_str;
+
+  cmd_str = gst_omx_command_to_string (cmd);
+
+  switch (cmd) {
+    case OMX_CommandStateSet:
+      return gst_structure_new ("SendCommand",
+          "command", G_TYPE_STRING, cmd_str,
+          "state", G_TYPE_STRING, gst_omx_state_to_string (param), NULL);
+    case OMX_CommandFlush:
+    case OMX_CommandPortDisable:
+    case OMX_CommandPortEnable:
+      return gst_structure_new ("SendCommand",
+          "command", G_TYPE_STRING, cmd_str, "port", G_TYPE_UINT, param, NULL);
+    case OMX_CommandMarkBuffer:
+      return gst_structure_new ("SendCommand",
+          "command", G_TYPE_STRING, cmd_str,
+          "mark-type", G_TYPE_POINTER, cmd_data, NULL);
+    case OMX_CommandKhronosExtensions:
+    case OMX_CommandVendorStartUnused:
+    case OMX_CommandMax:
+    default:
+      break;
+  }
+
+  return NULL;
+}
+
+static void
+log_omx_api_trace_send_command (GstOMXComponent * comp, OMX_COMMANDTYPE cmd,
+    guint32 param, gpointer cmd_data)
+{
+#ifndef GST_DISABLE_GST_DEBUG
+  GstStructure *s;
+
+  /* Don't bother creating useless structs if not needed */
+  if (gst_debug_category_get_threshold (OMX_API_TRACE) < GST_LEVEL_DEBUG)
+    return;
+
+  s = omx_command_to_debug_struct (cmd, param, cmd_data);
+  if (!s) {
+    GST_CAT_WARNING_OBJECT (OMX_API_TRACE, comp->parent,
+        "invalid command 0x%08x Param %u CmdData %p", cmd, param, cmd_data);
+    return;
+  }
+
+  GST_CAT_DEBUG_OBJECT (OMX_API_TRACE, comp->parent, "%" GST_PTR_FORMAT, s);
+
+  gst_structure_free (s);
+#endif /* GST_DISABLE_GST_DEBUG */
+}
+
+static OMX_ERRORTYPE
+gst_omx_component_send_command (GstOMXComponent * comp, OMX_COMMANDTYPE cmd,
+    guint32 param, gpointer cmd_data)
+{
+  OMX_ERRORTYPE err;
+
+  log_omx_api_trace_send_command (comp, cmd, param, cmd_data);
+  err = OMX_SendCommand (comp->handle, cmd, param, cmd_data);
+
+  return err;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_component_set_state (GstOMXComponent * comp, OMX_STATETYPE state)
+{
+  OMX_STATETYPE old_state;
+  OMX_ERRORTYPE err = OMX_ErrorNone;
+
+  g_return_val_if_fail (comp != NULL, OMX_ErrorUndefined);
+
+  g_mutex_lock (&comp->lock);
+
+  gst_omx_component_handle_messages (comp);
+
+  old_state = comp->state;
+  GST_INFO_OBJECT (comp->parent, "Setting %s state from %s to %s", comp->name,
+      gst_omx_state_to_string (old_state), gst_omx_state_to_string (state));
+
+  if ((err = comp->last_error) != OMX_ErrorNone && state > old_state) {
+    GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
+        comp->name, gst_omx_error_to_string (err), err);
+    goto done;
+  }
+
+  if (old_state == state || comp->pending_state == state) {
+    GST_DEBUG_OBJECT (comp->parent, "Component %s already in state %s",
+        comp->name, gst_omx_state_to_string (state));
+    goto done;
+  }
+
+  comp->pending_state = state;
+
+  /* Reset some things */
+  if ((old_state == OMX_StateExecuting || old_state == OMX_StatePause)
+      && state < old_state) {
+    g_list_free (comp->pending_reconfigure_outports);
+    comp->pending_reconfigure_outports = NULL;
+    /* Notify all inports that are still waiting */
+    gst_omx_component_send_message (comp, NULL);
+  }
+
+  err = gst_omx_component_send_command (comp, OMX_CommandStateSet, state, NULL);
+  /* No need to check if anything has changed here */
+
+done:
+
+  gst_omx_component_handle_messages (comp);
+
+  if (err != OMX_ErrorNone && comp->last_error == OMX_ErrorNone) {
+    GST_ERROR_OBJECT (comp->parent,
+        "Last operation returned an error. Setting last_error manually.");
+    comp->last_error = err;
+  }
+
+  g_mutex_unlock (&comp->lock);
+
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (comp->parent,
+        "Error setting %s state from %s to %s: %s (0x%08x)", comp->name,
+        gst_omx_state_to_string (old_state), gst_omx_state_to_string (state),
+        gst_omx_error_to_string (err), err);
+  }
+  return err;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_STATETYPE
+gst_omx_component_get_state (GstOMXComponent * comp, GstClockTime timeout)
+{
+  OMX_STATETYPE ret;
+  gboolean signalled = TRUE;
+
+  g_return_val_if_fail (comp != NULL, OMX_StateInvalid);
+
+  GST_DEBUG_OBJECT (comp->parent, "Getting state of %s", comp->name);
+
+  g_mutex_lock (&comp->lock);
+
+  gst_omx_component_handle_messages (comp);
+
+  if (comp->last_error != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
+        comp->name, gst_omx_error_to_string (comp->last_error),
+        comp->last_error);
+    ret = OMX_StateInvalid;
+    goto done;
+  }
+
+  ret = comp->state;
+  if (comp->pending_state == OMX_StateInvalid)
+    goto done;
+
+  while (signalled && comp->last_error == OMX_ErrorNone
+      && comp->pending_state != OMX_StateInvalid) {
+
+    signalled = gst_omx_component_wait_message (comp, timeout);
+    if (signalled)
+      gst_omx_component_handle_messages (comp);
+  };
+
+  if (signalled) {
+    if (comp->last_error != OMX_ErrorNone) {
+      GST_ERROR_OBJECT (comp->parent,
+          "%s got error while waiting for state change: %s (0x%08x)",
+          comp->name, gst_omx_error_to_string (comp->last_error),
+          comp->last_error);
+      ret = OMX_StateInvalid;
+    } else if (comp->pending_state == OMX_StateInvalid) {
+      /* State change finished and everything's fine */
+      ret = comp->state;
+    } else {
+      ret = OMX_StateInvalid;
+      g_assert_not_reached ();
+    }
+  } else {
+    ret = OMX_StateInvalid;
+    GST_WARNING_OBJECT (comp->parent, "%s timeout while waiting for state "
+        "change", comp->name);
+  }
+
+done:
+  g_mutex_unlock (&comp->lock);
+
+  GST_DEBUG_OBJECT (comp->parent, "%s returning state %s", comp->name,
+      gst_omx_state_to_string (ret));
+
+  return ret;
+}
+
+GstOMXPort *
+gst_omx_component_add_port (GstOMXComponent * comp, guint32 index)
+{
+  gint i, n;
+  GstOMXPort *port;
+  OMX_PARAM_PORTDEFINITIONTYPE port_def;
+  OMX_ERRORTYPE err;
+
+  g_return_val_if_fail (comp != NULL, NULL);
+
+  /* Check if this port exists already */
+  n = comp->ports->len;
+  for (i = 0; i < n; i++) {
+    port = g_ptr_array_index (comp->ports, i);
+    g_return_val_if_fail (port->index != index, NULL);
+  }
+
+  GST_DEBUG_OBJECT (comp->parent, "%s adding port %u", comp->name, index);
+
+  GST_OMX_INIT_STRUCT (&port_def);
+  port_def.nPortIndex = index;
+
+  err = gst_omx_component_get_parameter (comp, OMX_IndexParamPortDefinition,
+      &port_def);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (comp->parent, "%s failed to add port %u: %s (0x%08x)",
+        comp->name, index, gst_omx_error_to_string (err), err);
+    return NULL;
+  }
+
+  port = g_slice_new0 (GstOMXPort);
+  port->comp = comp;
+  port->index = index;
+
+  port->tunneled = FALSE;
+
+  port->port_def = port_def;
+
+  g_queue_init (&port->pending_buffers);
+  port->flushing = TRUE;
+  port->flushed = FALSE;
+  port->enabled_pending = FALSE;
+  port->disabled_pending = FALSE;
+  port->eos = FALSE;
+  port->using_pool = FALSE;
+
+  if (port->port_def.eDir == OMX_DirInput)
+    comp->n_in_ports++;
+  else
+    comp->n_out_ports++;
+
+  g_ptr_array_add (comp->ports, port);
+
+  return port;
+}
+
+GstOMXPort *
+gst_omx_component_get_port (GstOMXComponent * comp, guint32 index)
+{
+  gint i, n;
+
+  n = comp->ports->len;
+  for (i = 0; i < n; i++) {
+    GstOMXPort *tmp = g_ptr_array_index (comp->ports, i);
+
+    if (tmp->index == index)
+      return tmp;
+  }
+  return NULL;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_component_get_last_error (GstOMXComponent * comp)
+{
+  OMX_ERRORTYPE err;
+
+  g_return_val_if_fail (comp != NULL, OMX_ErrorUndefined);
+
+  g_mutex_lock (&comp->lock);
+  gst_omx_component_handle_messages (comp);
+  err = comp->last_error;
+  g_mutex_unlock (&comp->lock);
+
+  GST_DEBUG_OBJECT (comp->parent, "Returning last %s error: %s (0x%08x)",
+      comp->name, gst_omx_error_to_string (err), err);
+
+  return err;
+}
+
+const gchar *
+gst_omx_component_get_last_error_string (GstOMXComponent * comp)
+{
+  g_return_val_if_fail (comp != NULL, NULL);
+
+  return gst_omx_error_to_string (gst_omx_component_get_last_error (comp));
+}
+
+#ifndef GST_DISABLE_GST_DEBUG
+static const gchar *
+omx_index_type_to_str (OMX_INDEXTYPE index)
+{
+  switch (index) {
+    case OMX_IndexComponentStartUnused:
+      return "OMX_IndexComponentStartUnused";
+    case OMX_IndexParamPriorityMgmt:
+      return "OMX_IndexParamPriorityMgmt";
+    case OMX_IndexParamAudioInit:
+      return "OMX_IndexParamAudioInit";
+    case OMX_IndexParamImageInit:
+      return "OMX_IndexParamImageInit";
+    case OMX_IndexParamVideoInit:
+      return "OMX_IndexParamVideoInit";
+    case OMX_IndexParamOtherInit:
+      return "OMX_IndexParamOtherInit";
+    case OMX_IndexParamNumAvailableStreams:
+      return "OMX_IndexParamNumAvailableStreams";
+    case OMX_IndexParamActiveStream:
+      return "OMX_IndexParamActiveStream";
+    case OMX_IndexParamSuspensionPolicy:
+      return "OMX_IndexParamSuspensionPolicy";
+    case OMX_IndexParamComponentSuspended:
+      return "OMX_IndexParamComponentSuspended";
+    case OMX_IndexConfigCapturing:
+      return "OMX_IndexConfigCapturing";
+    case OMX_IndexConfigCaptureMode:
+      return "OMX_IndexConfigCaptureMode";
+    case OMX_IndexAutoPauseAfterCapture:
+      return "OMX_IndexAutoPauseAfterCapture";
+    case OMX_IndexParamContentURI:
+      return "OMX_IndexParamContentURI";
+    case OMX_IndexParamDisableResourceConcealment:
+      return "OMX_IndexParamDisableResourceConcealment";
+    case OMX_IndexConfigMetadataItemCount:
+      return "OMX_IndexConfigMetadataItemCount";
+    case OMX_IndexConfigContainerNodeCount:
+      return "OMX_IndexConfigContainerNodeCount";
+    case OMX_IndexConfigMetadataItem:
+      return "OMX_IndexConfigMetadataItem";
+    case OMX_IndexConfigCounterNodeID:
+      return "OMX_IndexConfigCounterNodeID";
+    case OMX_IndexParamMetadataFilterType:
+      return "OMX_IndexParamMetadataFilterType";
+    case OMX_IndexParamMetadataKeyFilter:
+      return "OMX_IndexParamMetadataKeyFilter";
+    case OMX_IndexConfigPriorityMgmt:
+      return "OMX_IndexConfigPriorityMgmt";
+    case OMX_IndexParamStandardComponentRole:
+      return "OMX_IndexParamStandardComponentRole";
+    case OMX_IndexPortStartUnused:
+      return "OMX_IndexPortStartUnused";
+    case OMX_IndexParamPortDefinition:
+      return "OMX_IndexParamPortDefinition";
+    case OMX_IndexParamCompBufferSupplier:
+      return "OMX_IndexParamCompBufferSupplier";
+    case OMX_IndexReservedStartUnused:
+      return "OMX_IndexReservedStartUnused";
+    case OMX_IndexAudioStartUnused:
+      return "OMX_IndexAudioStartUnused";
+    case OMX_IndexParamAudioPortFormat:
+      return "OMX_IndexParamAudioPortFormat";
+    case OMX_IndexParamAudioPcm:
+      return "OMX_IndexParamAudioPcm";
+    case OMX_IndexParamAudioAac:
+      return "OMX_IndexParamAudioAac";
+    case OMX_IndexParamAudioRa:
+      return "OMX_IndexParamAudioRa";
+    case OMX_IndexParamAudioMp3:
+      return "OMX_IndexParamAudioMp3";
+    case OMX_IndexParamAudioAdpcm:
+      return "OMX_IndexParamAudioAdpcm";
+    case OMX_IndexParamAudioG723:
+      return "OMX_IndexParamAudioG723";
+    case OMX_IndexParamAudioG729:
+      return "OMX_IndexParamAudioG729";
+    case OMX_IndexParamAudioAmr:
+      return "OMX_IndexParamAudioAmr";
+    case OMX_IndexParamAudioWma:
+      return "OMX_IndexParamAudioWma";
+    case OMX_IndexParamAudioSbc:
+      return "OMX_IndexParamAudioSbc";
+    case OMX_IndexParamAudioMidi:
+      return "OMX_IndexParamAudioMidi";
+    case OMX_IndexParamAudioGsm_FR:
+      return "OMX_IndexParamAudioGsm_FR";
+    case OMX_IndexParamAudioMidiLoadUserSound:
+      return "OMX_IndexParamAudioMidiLoadUserSound";
+    case OMX_IndexParamAudioG726:
+      return "OMX_IndexParamAudioG726";
+    case OMX_IndexParamAudioGsm_EFR:
+      return "OMX_IndexParamAudioGsm_EFR";
+    case OMX_IndexParamAudioGsm_HR:
+      return "OMX_IndexParamAudioGsm_HR";
+    case OMX_IndexParamAudioPdc_FR:
+      return "OMX_IndexParamAudioPdc_FR";
+    case OMX_IndexParamAudioPdc_EFR:
+      return "OMX_IndexParamAudioPdc_EFR";
+    case OMX_IndexParamAudioPdc_HR:
+      return "OMX_IndexParamAudioPdc_HR";
+    case OMX_IndexParamAudioTdma_FR:
+      return "OMX_IndexParamAudioTdma_FR";
+    case OMX_IndexParamAudioTdma_EFR:
+      return "OMX_IndexParamAudioTdma_EFR";
+    case OMX_IndexParamAudioQcelp8:
+      return "OMX_IndexParamAudioQcelp8";
+    case OMX_IndexParamAudioQcelp13:
+      return "OMX_IndexParamAudioQcelp13";
+    case OMX_IndexParamAudioEvrc:
+      return "OMX_IndexParamAudioEvrc";
+    case OMX_IndexParamAudioSmv:
+      return "OMX_IndexParamAudioSmv";
+    case OMX_IndexParamAudioVorbis:
+      return "OMX_IndexParamAudioVorbis";
+    case OMX_IndexConfigAudioMidiImmediateEvent:
+      return "OMX_IndexConfigAudioMidiImmediateEvent";
+    case OMX_IndexConfigAudioMidiControl:
+      return "OMX_IndexConfigAudioMidiControl";
+    case OMX_IndexConfigAudioMidiSoundBankProgram:
+      return "OMX_IndexConfigAudioMidiSoundBankProgram";
+    case OMX_IndexConfigAudioMidiStatus:
+      return "OMX_IndexConfigAudioMidiStatus";
+    case OMX_IndexConfigAudioMidiMetaEvent:
+      return "OMX_IndexConfigAudioMidiMetaEvent";
+    case OMX_IndexConfigAudioMidiMetaEventData:
+      return "OMX_IndexConfigAudioMidiMetaEventData";
+    case OMX_IndexConfigAudioVolume:
+      return "OMX_IndexConfigAudioVolume";
+    case OMX_IndexConfigAudioBalance:
+      return "OMX_IndexConfigAudioBalance";
+    case OMX_IndexConfigAudioChannelMute:
+      return "OMX_IndexConfigAudioChannelMute";
+    case OMX_IndexConfigAudioMute:
+      return "OMX_IndexConfigAudioMute";
+    case OMX_IndexConfigAudioLoudness:
+      return "OMX_IndexConfigAudioLoudness";
+    case OMX_IndexConfigAudioEchoCancelation:
+      return "OMX_IndexConfigAudioEchoCancelation";
+    case OMX_IndexConfigAudioNoiseReduction:
+      return "OMX_IndexConfigAudioNoiseReduction";
+    case OMX_IndexConfigAudioBass:
+      return "OMX_IndexConfigAudioBass";
+    case OMX_IndexConfigAudioTreble:
+      return "OMX_IndexConfigAudioTreble";
+    case OMX_IndexConfigAudioStereoWidening:
+      return "OMX_IndexConfigAudioStereoWidening";
+    case OMX_IndexConfigAudioChorus:
+      return "OMX_IndexConfigAudioChorus";
+    case OMX_IndexConfigAudioEqualizer:
+      return "OMX_IndexConfigAudioEqualizer";
+    case OMX_IndexConfigAudioReverberation:
+      return "OMX_IndexConfigAudioReverberation";
+    case OMX_IndexConfigAudioChannelVolume:
+      return "OMX_IndexConfigAudioChannelVolume";
+    case OMX_IndexImageStartUnused:
+      return "OMX_IndexImageStartUnused";
+    case OMX_IndexParamImagePortFormat:
+      return "OMX_IndexParamImagePortFormat";
+    case OMX_IndexParamFlashControl:
+      return "OMX_IndexParamFlashControl";
+    case OMX_IndexConfigFocusControl:
+      return "OMX_IndexConfigFocusControl";
+    case OMX_IndexParamQFactor:
+      return "OMX_IndexParamQFactor";
+    case OMX_IndexParamQuantizationTable:
+      return "OMX_IndexParamQuantizationTable";
+    case OMX_IndexParamHuffmanTable:
+      return "OMX_IndexParamHuffmanTable";
+    case OMX_IndexConfigFlashControl:
+      return "OMX_IndexConfigFlashControl";
+    case OMX_IndexVideoStartUnused:
+      return "OMX_IndexVideoStartUnused";
+    case OMX_IndexParamVideoPortFormat:
+      return "OMX_IndexParamVideoPortFormat";
+    case OMX_IndexParamVideoQuantization:
+      return "OMX_IndexParamVideoQuantization";
+    case OMX_IndexParamVideoFastUpdate:
+      return "OMX_IndexParamVideoFastUpdate";
+    case OMX_IndexParamVideoBitrate:
+      return "OMX_IndexParamVideoBitrate";
+    case OMX_IndexParamVideoMotionVector:
+      return "OMX_IndexParamVideoMotionVector";
+    case OMX_IndexParamVideoIntraRefresh:
+      return "OMX_IndexParamVideoIntraRefresh";
+    case OMX_IndexParamVideoErrorCorrection:
+      return "OMX_IndexParamVideoErrorCorrection";
+    case OMX_IndexParamVideoVBSMC:
+      return "OMX_IndexParamVideoVBSMC";
+    case OMX_IndexParamVideoMpeg2:
+      return "OMX_IndexParamVideoMpeg2";
+    case OMX_IndexParamVideoMpeg4:
+      return "OMX_IndexParamVideoMpeg4";
+    case OMX_IndexParamVideoWmv:
+      return "OMX_IndexParamVideoWmv";
+    case OMX_IndexParamVideoRv:
+      return "OMX_IndexParamVideoRv";
+    case OMX_IndexParamVideoAvc:
+      return "OMX_IndexParamVideoAvc";
+    case OMX_IndexParamVideoH263:
+      return "OMX_IndexParamVideoH263";
+    case OMX_IndexParamVideoProfileLevelQuerySupported:
+      return "OMX_IndexParamVideoProfileLevelQuerySupported";
+    case OMX_IndexParamVideoProfileLevelCurrent:
+      return "OMX_IndexParamVideoProfileLevelCurrent";
+    case OMX_IndexConfigVideoBitrate:
+      return "OMX_IndexConfigVideoBitrate";
+    case OMX_IndexConfigVideoFramerate:
+      return "OMX_IndexConfigVideoFramerate";
+    case OMX_IndexConfigVideoIntraVOPRefresh:
+      return "OMX_IndexConfigVideoIntraVOPRefresh";
+    case OMX_IndexConfigVideoIntraMBRefresh:
+      return "OMX_IndexConfigVideoIntraMBRefresh";
+    case OMX_IndexConfigVideoMBErrorReporting:
+      return "OMX_IndexConfigVideoMBErrorReporting";
+    case OMX_IndexParamVideoMacroblocksPerFrame:
+      return "OMX_IndexParamVideoMacroblocksPerFrame";
+    case OMX_IndexConfigVideoMacroBlockErrorMap:
+      return "OMX_IndexConfigVideoMacroBlockErrorMap";
+    case OMX_IndexParamVideoSliceFMO:
+      return "OMX_IndexParamVideoSliceFMO";
+    case OMX_IndexConfigVideoAVCIntraPeriod:
+      return "OMX_IndexConfigVideoAVCIntraPeriod";
+    case OMX_IndexConfigVideoNalSize:
+      return "OMX_IndexConfigVideoNalSize";
+    case OMX_IndexCommonStartUnused:
+      return "OMX_IndexCommonStartUnused";
+    case OMX_IndexParamCommonDeblocking:
+      return "OMX_IndexParamCommonDeblocking";
+    case OMX_IndexParamCommonSensorMode:
+      return "OMX_IndexParamCommonSensorMode";
+    case OMX_IndexParamCommonInterleave:
+      return "OMX_IndexParamCommonInterleave";
+    case OMX_IndexConfigCommonColorFormatConversion:
+      return "OMX_IndexConfigCommonColorFormatConversion";
+    case OMX_IndexConfigCommonScale:
+      return "OMX_IndexConfigCommonScale";
+    case OMX_IndexConfigCommonImageFilter:
+      return "OMX_IndexConfigCommonImageFilter";
+    case OMX_IndexConfigCommonColorEnhancement:
+      return "OMX_IndexConfigCommonColorEnhancement";
+    case OMX_IndexConfigCommonColorKey:
+      return "OMX_IndexConfigCommonColorKey";
+    case OMX_IndexConfigCommonColorBlend:
+      return "OMX_IndexConfigCommonColorBlend";
+    case OMX_IndexConfigCommonFrameStabilisation:
+      return "OMX_IndexConfigCommonFrameStabilisation";
+    case OMX_IndexConfigCommonRotate:
+      return "OMX_IndexConfigCommonRotate";
+    case OMX_IndexConfigCommonMirror:
+      return "OMX_IndexConfigCommonMirror";
+    case OMX_IndexConfigCommonOutputPosition:
+      return "OMX_IndexConfigCommonOutputPosition";
+    case OMX_IndexConfigCommonInputCrop:
+      return "OMX_IndexConfigCommonInputCrop";
+    case OMX_IndexConfigCommonOutputCrop:
+      return "OMX_IndexConfigCommonOutputCrop";
+    case OMX_IndexConfigCommonDigitalZoom:
+      return "OMX_IndexConfigCommonDigitalZoom";
+    case OMX_IndexConfigCommonOpticalZoom:
+      return "OMX_IndexConfigCommonOpticalZoom";
+    case OMX_IndexConfigCommonWhiteBalance:
+      return "OMX_IndexConfigCommonWhiteBalance";
+    case OMX_IndexConfigCommonExposure:
+      return "OMX_IndexConfigCommonExposure";
+    case OMX_IndexConfigCommonContrast:
+      return "OMX_IndexConfigCommonContrast";
+    case OMX_IndexConfigCommonBrightness:
+      return "OMX_IndexConfigCommonBrightness";
+    case OMX_IndexConfigCommonBacklight:
+      return "OMX_IndexConfigCommonBacklight";
+    case OMX_IndexConfigCommonGamma:
+      return "OMX_IndexConfigCommonGamma";
+    case OMX_IndexConfigCommonSaturation:
+      return "OMX_IndexConfigCommonSaturation";
+    case OMX_IndexConfigCommonLightness:
+      return "OMX_IndexConfigCommonLightness";
+    case OMX_IndexConfigCommonExclusionRect:
+      return "OMX_IndexConfigCommonExclusionRect";
+    case OMX_IndexConfigCommonDithering:
+      return "OMX_IndexConfigCommonDithering";
+    case OMX_IndexConfigCommonPlaneBlend:
+      return "OMX_IndexConfigCommonPlaneBlend";
+    case OMX_IndexConfigCommonExposureValue:
+      return "OMX_IndexConfigCommonExposureValue";
+    case OMX_IndexConfigCommonOutputSize:
+      return "OMX_IndexConfigCommonOutputSize";
+    case OMX_IndexParamCommonExtraQuantData:
+      return "OMX_IndexParamCommonExtraQuantData";
+    case OMX_IndexConfigCommonTransitionEffect:
+      return "OMX_IndexConfigCommonTransitionEffect";
+    case OMX_IndexOtherStartUnused:
+      return "OMX_IndexOtherStartUnused";
+    case OMX_IndexParamOtherPortFormat:
+      return "OMX_IndexParamOtherPortFormat";
+    case OMX_IndexConfigOtherPower:
+      return "OMX_IndexConfigOtherPower";
+    case OMX_IndexConfigOtherStats:
+      return "OMX_IndexConfigOtherStats";
+    case OMX_IndexTimeStartUnused:
+      return "OMX_IndexTimeStartUnused";
+    case OMX_IndexConfigTimeScale:
+      return "OMX_IndexConfigTimeScale";
+    case OMX_IndexConfigTimeClockState:
+      return "OMX_IndexConfigTimeClockState";
+    case OMX_IndexConfigTimeCurrentMediaTime:
+      return "OMX_IndexConfigTimeCurrentMediaTime";
+    case OMX_IndexConfigTimeCurrentWallTime:
+      return "OMX_IndexConfigTimeCurrentWallTime";
+    case OMX_IndexConfigTimeMediaTimeRequest:
+      return "OMX_IndexConfigTimeMediaTimeRequest";
+    case OMX_IndexConfigTimeClientStartTime:
+      return "OMX_IndexConfigTimeClientStartTime";
+    case OMX_IndexConfigTimePosition:
+      return "OMX_IndexConfigTimePosition";
+    case OMX_IndexConfigTimeSeekMode:
+      return "OMX_IndexConfigTimeSeekMode";
+    case OMX_IndexKhronosExtensions:
+      return "OMX_IndexKhronosExtensions";
+    case OMX_IndexVendorStartUnused:
+      return "OMX_IndexVendorStartUnused";
+    case OMX_IndexMax:
+      return "OMX_IndexMax";
+    default:
+      break;
+  }
+
+#if OMX_VERSION_MINOR == 1
+  switch (index) {
+    case OMX_IndexParamCustomContentPipe:
+      return "OMX_IndexParamCustomContentPipe";
+    case OMX_IndexConfigCommonFocusRegion:
+      return "OMX_IndexConfigCommonFocusRegion";
+    case OMX_IndexConfigCommonFocusStatus:
+      return "OMX_IndexConfigCommonFocusStatus";
+    case OMX_IndexConfigTimeActiveRefClock:
+      return "OMX_IndexConfigTimeActiveRefClock";
+    case OMX_IndexConfigTimeCurrentAudioReference:
+      return "OMX_IndexConfigTimeCurrentAudioReference";
+    case OMX_IndexConfigTimeCurrentVideoReference:
+      return "OMX_IndexConfigTimeCurrentVideoReference";
+    default:
+      break;
+  }
+#endif
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+  switch ((OMX_ALG_INDEXTYPE) index) {
+    case OMX_ALG_IndexVendorComponentStartUnused:
+      return "OMX_ALG_IndexVendorComponentStartUnused";
+    case OMX_ALG_IndexParamReportedLatency:
+      return "OMX_ALG_IndexParamReportedLatency";
+    case OMX_ALG_IndexParamPreallocation:
+      return "OMX_ALG_IndexParamPreallocation";
+    case OMX_ALG_IndexVendorPortStartUnused:
+      return "OMX_ALG_IndexVendorPortStartUnused";
+    case OMX_ALG_IndexPortParamBufferMode:
+      return "OMX_ALG_IndexPortParamBufferMode";
+    case OMX_ALG_IndexParamVendorVideoStartUnused:
+      return "OMX_ALG_IndexParamVendorVideoStartUnused";
+    case OMX_ALG_IndexParamVideoHevc:
+      return "OMX_ALG_IndexParamVideoHevc";
+    case OMX_ALG_IndexParamVideoVp9:
+      return "OMX_ALG_IndexParamVideoVp9";
+    case OMX_ALG_IndexParamVideoGopControl:
+      return "OMX_ALG_IndexParamVideoGopControl";
+    case OMX_ALG_IndexParamVideoSlices:
+      return "OMX_ALG_IndexParamVideoSlices";
+    case OMX_ALG_IndexParamVideoSceneChangeResilience:
+      return "OMX_ALG_IndexParamVideoSceneChangeResilience";
+    case OMX_ALG_IndexParamVideoPrefetchBuffer:
+      return "OMX_ALG_IndexParamVideoPrefetchBuffer";
+    case OMX_ALG_IndexParamVideoCodedPictureBuffer:
+      return "OMX_ALG_IndexParamVideoCodedPictureBuffer";
+    case OMX_ALG_IndexParamVideoQuantizationControl:
+      return "OMX_ALG_IndexParamVideoQuantizationControl";
+    case OMX_ALG_IndexParamVideoQuantizationExtension:
+      return "OMX_ALG_IndexParamVideoQuantizationExtension";
+    case OMX_ALG_IndexParamVideoScalingList:
+      return "OMX_ALG_IndexParamVideoScalingList";
+    case OMX_ALG_IndexParamVideoDecodedPictureBuffer:
+      return "OMX_ALG_IndexParamVideoDecodedPictureBuffer";
+    case OMX_ALG_IndexParamVideoInternalEntropyBuffers:
+      return "OMX_ALG_IndexParamVideoInternalEntropyBuffers";
+    case OMX_ALG_IndexParamVideoLowBandwidth:
+      return "OMX_ALG_IndexParamVideoLowBandwidth";
+    case OMX_ALG_IndexParamVideoAspectRatio:
+      return "OMX_ALG_IndexParamVideoAspectRatio";
+    case OMX_ALG_IndexParamVideoSubframe:
+      return "OMX_ALG_IndexParamVideoSubframe";
+    case OMX_ALG_IndexParamVideoInstantaneousDecodingRefresh:
+      return "OMX_ALG_IndexParamVideoInstantaneousDecodingRefresh";
+    case OMX_ALG_IndexParamVideoMaxBitrate:
+      return "OMX_ALG_IndexParamVideoMaxBitrate";
+    case OMX_ALG_IndexParamVideoFillerData:
+      return "OMX_ALG_IndexParamVideoFillerData";
+    case OMX_ALG_IndexParamVideoBufferMode:
+      return "OMX_ALG_IndexParamVideoBufferMode";
+    case OMX_ALG_IndexParamVideoInterlaceFormatCurrent:
+      return "OMX_ALG_IndexParamVideoInterlaceFormatCurrent";
+    case OMX_ALG_IndexParamVideoLongTerm:
+      return "OMX_ALG_IndexParamVideoLongTerm";
+    case OMX_ALG_IndexParamVideoLookAhead:
+      return "OMX_ALG_IndexParamVideoLookAhead";
+    case OMX_ALG_IndexConfigVendorVideoStartUnused:
+      return "OMX_ALG_IndexConfigVendorVideoStartUnused";
+    case OMX_ALG_IndexConfigVideoInsertInstantaneousDecodingRefresh:
+      return "OMX_ALG_IndexConfigVideoInsertInstantaneousDecodingRefresh";
+    case OMX_ALG_IndexConfigVideoGroupOfPictures:
+      return "OMX_ALG_IndexConfigVideoGroupOfPictures";
+    case OMX_ALG_IndexConfigVideoRegionOfInterest:
+      return "OMX_ALG_IndexConfigVideoRegionOfInterest";
+    case OMX_ALG_IndexConfigVideoNotifySceneChange:
+      return "OMX_ALG_IndexConfigVideoNotifySceneChange";
+    case OMX_ALG_IndexConfigVideoInsertLongTerm:
+      return "OMX_ALG_IndexConfigVideoInsertLongTerm";
+    case OMX_ALG_IndexConfigVideoUseLongTerm:
+      return "OMX_ALG_IndexConfigVideoUseLongTerm";
+    case OMX_ALG_IndexVendorCommonStartUnused:
+      return "OMX_ALG_IndexVendorCommonStartUnused";
+    case OMX_ALG_IndexParamCommonSequencePictureModeCurrent:
+      return "OMX_ALG_IndexParamCommonSequencePictureModeCurrent";
+    case OMX_ALG_IndexParamCommonSequencePictureModeQuerySupported:
+      return "OMX_ALG_IndexParamCommonSequencePictureModeQuerySupported";
+    case OMX_ALG_IndexParamVideoTwoPass:
+      return "OMX_ALG_IndexParamVideoTwoPass";
+    case OMX_ALG_IndexParamVideoColorPrimaries:
+      return "OMX_ALG_IndexParamVideoColorPrimaries";
+    case OMX_ALG_IndexParamVideoSkipFrame:
+      return "OMX_ALG_IndexParamVideoSkipFrame";
+    case OMX_ALG_IndexConfigVideoNotifyResolutionChange:
+      return "OMX_ALG_IndexConfigVideoNotifyResolutionChange";
+    case OMX_ALG_IndexConfigVideoInsertPrefixSEI:
+      return "OMX_ALG_IndexConfigVideoInsertPrefixSEI";
+    case OMX_ALG_IndexConfigVideoInsertSuffixSEI:
+      return "OMX_ALG_IndexConfigVideoInsertSuffixSEI";
+    case OMX_ALG_IndexConfigVideoQuantizationParameterTable:
+      return "OMX_ALG_IndexConfigVideoQuantizationParameterTable";
+    case OMX_ALG_IndexParamVideoInputParsed:
+      return "OMX_ALG_IndexParamVideoInputParsed";
+    case OMX_ALG_IndexParamVideoMaxPictureSize:
+      return "OMX_ALG_IndexParamVideoMaxPictureSize";
+    case OMX_ALG_IndexParamVideoMaxPictureSizes:
+      return "OMX_ALG_IndexParamVideoMaxPictureSizes";
+    case OMX_ALG_IndexConfigVideoLoopFilterBeta:
+      return "OMX_ALG_IndexConfigVideoLoopFilterBeta";
+    case OMX_ALG_IndexConfigVideoLoopFilterTc:
+      return "OMX_ALG_IndexConfigVideoLoopFilterTc";
+    case OMX_ALG_IndexParamVideoLoopFilterBeta:
+      return "OMX_ALG_IndexParamVideoLoopFilterBeta";
+    case OMX_ALG_IndexParamVideoLoopFilterTc:
+      return "OMX_ALG_IndexParamVideoLoopFilterTc";
+    case OMX_ALG_IndexPortParamEarlyCallback:
+      return "OMX_ALG_IndexPortParamEarlyCallback";
+    case OMX_ALG_IndexParamVideoTransferCharacteristics:
+      return "OMX_ALG_IndexParamVideoTransferCharacteristics";
+    case OMX_ALG_IndexParamVideoColorMatrix:
+      return "OMX_ALG_IndexParamVideoColorMatrix";
+    case OMX_ALG_IndexConfigVideoTransferCharacteristics:
+      return "OMX_ALG_IndexConfigVideoTransferCharacteristics";
+    case OMX_ALG_IndexConfigVideoColorMatrix:
+      return "OMX_ALG_IndexConfigVideoColorMatrix";
+    case OMX_ALG_IndexConfigVideoHighDynamicRangeSEI:
+      return "OMX_ALG_IndexConfigVideoHighDynamicRangeSEI";
+    case OMX_ALG_IndexConfigVideoMaxResolutionChange:
+      return "OMX_ALG_IndexConfigVideoMaxResolutionChange";
+    case OMX_ALG_IndexParamVideoQuantizationTable:
+      return "OMX_ALG_IndexParamVideoQuantizationTable";
+    case OMX_ALG_IndexParamVideoAccessUnitDelimiter:
+      return "OMX_ALG_IndexParamVideoAccessUnitDelimiter";
+    case OMX_ALG_IndexParamVideoBufferingPeriodSEI:
+      return "OMX_ALG_IndexParamVideoBufferingPeriodSEI";
+    case OMX_ALG_IndexParamVideoPictureTimingSEI:
+      return "OMX_ALG_IndexParamVideoPictureTimingSEI";
+    case OMX_ALG_IndexParamVideoRecoveryPointSEI:
+      return "OMX_ALG_IndexParamVideoRecoveryPointSEI";
+    case OMX_ALG_IndexParamVideoMasteringDisplayColourVolumeSEI:
+      return "OMX_ALG_IndexParamVideoMasteringDisplayColourVolumeSEI";
+    case OMX_ALG_IndexParamVideoContentLightLevelSEI:
+      return "OMX_ALG_IndexParamVideoContentLightLevelSEI";
+    case OMX_ALG_IndexConfigVideoRegionOfInterestByValue:
+      return "OMX_ALG_IndexConfigVideoRegionOfInterestByValue";
+    case OMX_ALG_IndexConfigVideoColorPrimaries:
+      return "OMX_ALG_IndexConfigVideoColorPrimaries";
+    case OMX_ALG_IndexMaxEnum:
+      return "OMX_ALG_IndexMaxEnum";
+  }
+#endif
+
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+  /* Not part of the enum in OMX_IndexAlg.h */
+  if (index == OMX_ALG_IndexParamVideoInterlaceFormatSupported)
+    return "OMX_ALG_IndexParamVideoInterlaceFormatSupported";
+#endif
+
+  return NULL;
+}
+#endif /* GST_DISABLE_GST_DEBUG */
+
+static void
+log_omx_api_trace_call (GstOMXComponent * comp, const gchar * function,
+    OMX_INDEXTYPE index, GstDebugLevel level)
+{
+#ifndef GST_DISABLE_GST_DEBUG
+  GstStructure *s;
+  const gchar *index_name;
+
+  /* Don't bother creating useless structs if not needed */
+  if (gst_debug_category_get_threshold (OMX_API_TRACE) < level)
+    return;
+
+  index_name = omx_index_type_to_str (index);
+  if (!index_name) {
+    GST_CAT_WARNING_OBJECT (OMX_API_TRACE, comp->parent,
+        "unknown call of %s with index 0x%08x", function, index);
+    return;
+  }
+
+  s = gst_structure_new (function, "index", G_TYPE_STRING, index_name, NULL);
+  GST_CAT_LEVEL_LOG (OMX_API_TRACE, level, comp->parent, "%" GST_PTR_FORMAT, s);
+  gst_structure_free (s);
+#endif /* GST_DISABLE_GST_DEBUG */
+}
+
+/* comp->lock must be unlocked while calling this */
+OMX_ERRORTYPE
+gst_omx_component_get_parameter (GstOMXComponent * comp, OMX_INDEXTYPE index,
+    gpointer param)
+{
+  OMX_ERRORTYPE err;
+
+  g_return_val_if_fail (comp != NULL, OMX_ErrorUndefined);
+  g_return_val_if_fail (param != NULL, OMX_ErrorUndefined);
+
+  GST_DEBUG_OBJECT (comp->parent, "Getting %s parameter at index 0x%08x",
+      comp->name, index);
+  log_omx_api_trace_call (comp, "GetParameter", index, GST_LEVEL_LOG);
+  err = OMX_GetParameter (comp->handle, index, param);
+  DEBUG_IF_OK (comp->parent, err, "Got %s parameter at index 0x%08x: %s "
+      "(0x%08x)", comp->name, index, gst_omx_error_to_string (err), err);
+
+  return err;
+}
+
+/* comp->lock must be unlocked while calling this */
+OMX_ERRORTYPE
+gst_omx_component_set_parameter (GstOMXComponent * comp, OMX_INDEXTYPE index,
+    gpointer param)
+{
+  OMX_ERRORTYPE err;
+
+  g_return_val_if_fail (comp != NULL, OMX_ErrorUndefined);
+  g_return_val_if_fail (param != NULL, OMX_ErrorUndefined);
+
+  GST_DEBUG_OBJECT (comp->parent, "Setting %s parameter at index 0x%08x",
+      comp->name, index);
+
+  log_omx_api_trace_call (comp, "SetParameter", index, GST_LEVEL_DEBUG);
+  err = OMX_SetParameter (comp->handle, index, param);
+  DEBUG_IF_OK (comp->parent, err, "Set %s parameter at index 0x%08x: %s "
+      "(0x%08x)", comp->name, index, gst_omx_error_to_string (err), err);
+
+  return err;
+}
+
+/* comp->lock must be unlocked while calling this */
+OMX_ERRORTYPE
+gst_omx_component_get_config (GstOMXComponent * comp, OMX_INDEXTYPE index,
+    gpointer config)
+{
+  OMX_ERRORTYPE err;
+
+  g_return_val_if_fail (comp != NULL, OMX_ErrorUndefined);
+  g_return_val_if_fail (config != NULL, OMX_ErrorUndefined);
+
+  GST_DEBUG_OBJECT (comp->parent, "Getting %s configuration at index 0x%08x",
+      comp->name, index);
+  log_omx_api_trace_call (comp, "GetConfig", index, GST_LEVEL_LOG);
+  err = OMX_GetConfig (comp->handle, index, config);
+  DEBUG_IF_OK (comp->parent, err, "Got %s parameter at index 0x%08x: %s "
+      "(0x%08x)", comp->name, index, gst_omx_error_to_string (err), err);
+
+  return err;
+}
+
+/* comp->lock must be unlocked while calling this */
+OMX_ERRORTYPE
+gst_omx_component_set_config (GstOMXComponent * comp, OMX_INDEXTYPE index,
+    gpointer config)
+{
+  OMX_ERRORTYPE err;
+
+  g_return_val_if_fail (comp != NULL, OMX_ErrorUndefined);
+  g_return_val_if_fail (config != NULL, OMX_ErrorUndefined);
+
+  GST_DEBUG_OBJECT (comp->parent, "Setting %s configuration at index 0x%08x",
+      comp->name, index);
+  log_omx_api_trace_call (comp, "SetConfig", index, GST_LEVEL_DEBUG);
+  err = OMX_SetConfig (comp->handle, index, config);
+  DEBUG_IF_OK (comp->parent, err, "Set %s parameter at index 0x%08x: %s "
+      "(0x%08x)", comp->name, index, gst_omx_error_to_string (err), err);
+
+  return err;
+}
+
+OMX_ERRORTYPE
+gst_omx_setup_tunnel (GstOMXPort * port1, GstOMXPort * port2)
+{
+  GstOMXComponent *comp1;
+  GstOMXComponent *comp2;
+  OMX_ERRORTYPE err;
+
+  g_return_val_if_fail (port1 != NULL, OMX_ErrorUndefined);
+  g_return_val_if_fail (port1->port_def.eDir == OMX_DirOutput,
+      OMX_ErrorUndefined);
+  comp1 = port1->comp;
+
+  g_return_val_if_fail (port2 != NULL, OMX_ErrorUndefined);
+  g_return_val_if_fail (port2->port_def.eDir == OMX_DirInput,
+      OMX_ErrorUndefined);
+  comp2 = port2->comp;
+
+  g_return_val_if_fail (comp1->core == comp2->core, OMX_ErrorUndefined);
+
+  g_mutex_lock (&comp1->lock);
+  g_mutex_lock (&comp2->lock);
+  GST_DEBUG_OBJECT (comp1->parent,
+      "Setup tunnel between %s port %u and %s port %u",
+      comp1->name, port1->index, comp2->name, port2->index);
+
+  err = comp1->core->setup_tunnel (comp1->handle, port1->index, comp2->handle,
+      port2->index);
+
+  if (err == OMX_ErrorNone) {
+    port1->tunneled = TRUE;
+    port2->tunneled = TRUE;
+  }
+
+  DEBUG_IF_OK (comp1->parent, err,
+      "Setup tunnel between %s port %u and %s port %u: %s (0x%08x)",
+      comp1->name, port1->index,
+      comp2->name, port2->index, gst_omx_error_to_string (err), err);
+
+  g_mutex_unlock (&comp2->lock);
+  g_mutex_unlock (&comp1->lock);
+
+  return err;
+}
+
+OMX_ERRORTYPE
+gst_omx_close_tunnel (GstOMXPort * port1, GstOMXPort * port2)
+{
+  GstOMXComponent *comp1;
+  GstOMXComponent *comp2;
+  OMX_ERRORTYPE err;
+
+  g_return_val_if_fail (port1 != NULL, OMX_ErrorUndefined);
+  g_return_val_if_fail (port1->port_def.eDir == OMX_DirOutput,
+      OMX_ErrorUndefined);
+  comp1 = port1->comp;
+
+  g_return_val_if_fail (port2 != NULL, OMX_ErrorUndefined);
+  g_return_val_if_fail (port2->port_def.eDir == OMX_DirInput,
+      OMX_ErrorUndefined);
+  comp2 = port2->comp;
+
+  g_return_val_if_fail (comp1->core == comp2->core, OMX_ErrorUndefined);
+  g_return_val_if_fail (port1->tunneled && port2->tunneled, OMX_ErrorUndefined);
+
+  g_mutex_lock (&comp1->lock);
+  g_mutex_lock (&comp2->lock);
+  GST_DEBUG_OBJECT (comp1->parent,
+      "Closing tunnel between %s port %u and %s port %u",
+      comp1->name, port1->index, comp2->name, port2->index);
+
+  err = comp1->core->setup_tunnel (comp1->handle, port1->index, 0, 0);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (comp1->parent,
+        "Failed to close tunnel on output side %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+  }
+  err = comp2->core->setup_tunnel (0, 0, comp2->handle, port2->index);
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (comp2->parent,
+        "Failed to close tunnel on input side %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+  }
+
+  port1->tunneled = FALSE;
+  port2->tunneled = FALSE;
+
+  GST_DEBUG_OBJECT (comp1->parent,
+      "Closed tunnel between %s port %u and %s port %u",
+      comp1->name, port1->index, comp2->name, port2->index);
+
+  g_mutex_unlock (&comp2->lock);
+  g_mutex_unlock (&comp1->lock);
+
+  return err;
+}
+
+OMX_ERRORTYPE
+gst_omx_port_get_port_definition (GstOMXPort * port,
+    OMX_PARAM_PORTDEFINITIONTYPE * port_def)
+{
+  GstOMXComponent *comp;
+  OMX_ERRORTYPE err;
+
+  g_return_val_if_fail (port != NULL, OMX_ErrorBadParameter);
+
+  comp = port->comp;
+
+  GST_OMX_INIT_STRUCT (port_def);
+  port_def->nPortIndex = port->index;
+
+  err = gst_omx_component_get_parameter (comp, OMX_IndexParamPortDefinition,
+      port_def);
+
+  return err;
+}
+
+OMX_ERRORTYPE
+gst_omx_port_update_port_definition (GstOMXPort * port,
+    OMX_PARAM_PORTDEFINITIONTYPE * port_def)
+{
+  OMX_ERRORTYPE err_get, err_set = OMX_ErrorNone;
+  GstOMXComponent *comp;
+
+  g_return_val_if_fail (port != NULL, FALSE);
+
+  comp = port->comp;
+
+  if (port_def)
+    err_set =
+        gst_omx_component_set_parameter (comp, OMX_IndexParamPortDefinition,
+        port_def);
+  err_get = gst_omx_component_get_parameter (comp, OMX_IndexParamPortDefinition,
+      &port->port_def);
+
+  DEBUG_IF_OK (comp->parent, err_set,
+      "Updated %s port %u definition: %s (0x%08x)", comp->name, port->index,
+      gst_omx_error_to_string (err_set), err_set);
+
+  if (err_set != OMX_ErrorNone)
+    return err_set;
+  else
+    return err_get;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+GstOMXAcquireBufferReturn
+gst_omx_port_acquire_buffer (GstOMXPort * port, GstOMXBuffer ** buf,
+    GstOMXWait wait)
+{
+  GstOMXAcquireBufferReturn ret = GST_OMX_ACQUIRE_BUFFER_ERROR;
+  GstOMXComponent *comp;
+  OMX_ERRORTYPE err;
+  GstOMXBuffer *_buf = NULL;
+  gint64 timeout = GST_CLOCK_TIME_NONE;
+
+  g_return_val_if_fail (port != NULL, GST_OMX_ACQUIRE_BUFFER_ERROR);
+  g_return_val_if_fail (!port->tunneled, GST_OMX_ACQUIRE_BUFFER_ERROR);
+  g_return_val_if_fail (buf != NULL, GST_OMX_ACQUIRE_BUFFER_ERROR);
+
+  *buf = NULL;
+
+  comp = port->comp;
+
+  g_mutex_lock (&comp->lock);
+  GST_DEBUG_OBJECT (comp->parent, "Acquiring %s buffer from port %u",
+      comp->name, port->index);
+
+retry:
+  gst_omx_component_handle_messages (comp);
+
+  /* If we are in the case where we waited for a buffer after EOS,
+   * make sure we don't do that again */
+  if (timeout != -1)
+    timeout = -2;
+
+  /* Check if the component is in an error state */
+  if ((err = comp->last_error) != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (comp->parent, "Component %s is in error state: %s",
+        comp->name, gst_omx_error_to_string (err));
+    ret = GST_OMX_ACQUIRE_BUFFER_ERROR;
+    goto done;
+  }
+
+  /* Check if the port is flushing */
+  if (port->flushing) {
+    GST_DEBUG_OBJECT (comp->parent, "Component %s port %d is flushing",
+        comp->name, port->index);
+    ret = GST_OMX_ACQUIRE_BUFFER_FLUSHING;
+    goto done;
+  }
+
+  /* If this is an input port and at least one of the output ports
+   * needs to be reconfigured, we wait until all output ports are
+   * reconfigured. Afterwards this port is reconfigured if required
+   * or buffers are returned to be filled as usual.
+   */
+  if (port->port_def.eDir == OMX_DirInput) {
+    if (comp->pending_reconfigure_outports) {
+      gst_omx_component_handle_messages (comp);
+      while (comp->pending_reconfigure_outports &&
+          (err = comp->last_error) == OMX_ErrorNone && !port->flushing) {
+        GST_DEBUG_OBJECT (comp->parent,
+            "Waiting for %s output ports to reconfigure", comp->name);
+        gst_omx_component_wait_message (comp, GST_CLOCK_TIME_NONE);
+        gst_omx_component_handle_messages (comp);
+      }
+      goto retry;
+    }
+
+    /* Only if this port needs to be reconfigured too notify
+     * the caller about it */
+    if (port->settings_cookie != port->configured_settings_cookie) {
+      GST_DEBUG_OBJECT (comp->parent,
+          "Component %s port %d needs reconfiguring", comp->name, port->index);
+      ret = GST_OMX_ACQUIRE_BUFFER_RECONFIGURE;
+      goto done;
+    }
+  }
+
+  /* If we have an output port that needs to be reconfigured
+   * and it still has buffers pending for the old configuration
+   * we first return them.
+   * NOTE: If buffers for this configuration arrive later
+   * we have to drop them... */
+  if (port->port_def.eDir == OMX_DirOutput &&
+      port->settings_cookie != port->configured_settings_cookie) {
+    if (!g_queue_is_empty (&port->pending_buffers)) {
+      GST_DEBUG_OBJECT (comp->parent,
+          "%s output port %u needs reconfiguration but has buffers pending",
+          comp->name, port->index);
+      _buf = g_queue_pop_head (&port->pending_buffers);
+
+      ret = GST_OMX_ACQUIRE_BUFFER_OK;
+      goto done;
+    }
+
+    GST_DEBUG_OBJECT (comp->parent, "Component %s port %d needs reconfiguring",
+        comp->name, port->index);
+    ret = GST_OMX_ACQUIRE_BUFFER_RECONFIGURE;
+    goto done;
+  }
+
+  if (port->port_def.eDir == OMX_DirOutput && port->eos) {
+    if (!g_queue_is_empty (&port->pending_buffers)) {
+      GST_DEBUG_OBJECT (comp->parent, "%s output port %u is EOS but has "
+          "%d buffers pending", comp->name, port->index,
+          g_queue_get_length (&port->pending_buffers));
+      _buf = g_queue_pop_head (&port->pending_buffers);
+
+      ret = GST_OMX_ACQUIRE_BUFFER_OK;
+      goto done;
+    }
+
+    if (comp->hacks & GST_OMX_HACK_SIGNALS_PREMATURE_EOS && timeout != -2) {
+      timeout = 33 * GST_MSECOND;
+
+      GST_DEBUG_OBJECT (comp->parent, "%s output port %u is EOS but waiting "
+          "in case it spits out more buffers", comp->name, port->index);
+    } else {
+      GST_DEBUG_OBJECT (comp->parent, "Component %s port %d signalled EOS",
+          comp->name, port->index);
+      ret = GST_OMX_ACQUIRE_BUFFER_EOS;
+      port->eos = FALSE;
+      goto done;
+    }
+  }
+
+  /*
+   * At this point we have no error or flushing/eos port
+   * and a properly configured port.
+   *
+   */
+
+  /* If the queue is empty we wait until a buffer
+   * arrives, an error happens, the port is flushing
+   * or the port needs to be reconfigured.
+   */
+  if (g_queue_is_empty (&port->pending_buffers)) {
+    GST_DEBUG_OBJECT (comp->parent, "Queue of %s port %u is empty",
+        comp->name, port->index);
+
+    if (wait == GST_OMX_WAIT) {
+      gst_omx_component_wait_message (comp,
+          timeout == -2 ? GST_CLOCK_TIME_NONE : timeout);
+
+      /* And now check everything again and maybe get a buffer */
+      goto retry;
+    } else {
+      ret = GST_OMX_ACQUIRE_BUFFER_NO_AVAILABLE;
+      goto done;
+    }
+  }
+
+  GST_DEBUG_OBJECT (comp->parent, "%s port %u has pending buffers",
+      comp->name, port->index);
+  _buf = g_queue_pop_head (&port->pending_buffers);
+  ret = GST_OMX_ACQUIRE_BUFFER_OK;
+
+done:
+  g_mutex_unlock (&comp->lock);
+
+  if (_buf) {
+    g_assert (_buf == _buf->omx_buf->pAppPrivate);
+    *buf = _buf;
+  }
+
+  GST_DEBUG_OBJECT (comp->parent, "Acquired buffer %p (%p) from %s port %u: %d",
+      _buf, (_buf ? _buf->omx_buf->pBuffer : NULL), comp->name, port->index,
+      ret);
+
+  return ret;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_release_buffer (GstOMXPort * port, GstOMXBuffer * buf)
+{
+  GstOMXComponent *comp;
+  OMX_ERRORTYPE err = OMX_ErrorNone;
+
+  g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+  g_return_val_if_fail (!port->tunneled, OMX_ErrorUndefined);
+  g_return_val_if_fail (buf != NULL, OMX_ErrorUndefined);
+  g_return_val_if_fail (buf->port == port, OMX_ErrorUndefined);
+
+  comp = port->comp;
+
+  g_mutex_lock (&comp->lock);
+
+  GST_DEBUG_OBJECT (comp->parent, "Releasing buffer %p (%p) to %s port %u",
+      buf, buf->omx_buf->pBuffer, comp->name, port->index);
+
+  gst_omx_component_handle_messages (comp);
+
+  if (port->port_def.eDir == OMX_DirOutput) {
+    /* Reset all flags, some implementations don't
+     * reset them themselves and the flags are not
+     * valid anymore after the buffer was consumed
+     */
+    gst_omx_buffer_reset (buf);
+  }
+
+  if ((err = comp->last_error) != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (comp->parent, "Component %s is in error state: %s "
+        "(0x%08x)", comp->name, gst_omx_error_to_string (err), err);
+    g_queue_push_tail (&port->pending_buffers, buf);
+    gst_omx_component_send_message (comp, NULL);
+    goto done;
+  }
+
+  if (port->flushing || port->disabled_pending || !port->port_def.bEnabled) {
+    GST_DEBUG_OBJECT (comp->parent,
+        "%s port %u is flushing or disabled, not releasing " "buffer",
+        comp->name, port->index);
+    g_queue_push_tail (&port->pending_buffers, buf);
+    gst_omx_component_send_message (comp, NULL);
+    goto done;
+  }
+
+  g_assert (buf == buf->omx_buf->pAppPrivate);
+
+  /* FIXME: What if the settings cookies don't match? */
+
+  buf->used = TRUE;
+
+  if (port->port_def.eDir == OMX_DirInput) {
+    log_omx_api_trace_buffer (comp, "EmptyThisBuffer", buf);
+    err = OMX_EmptyThisBuffer (comp->handle, buf->omx_buf);
+  } else {
+    log_omx_api_trace_buffer (comp, "FillThisBuffer", buf);
+    err = OMX_FillThisBuffer (comp->handle, buf->omx_buf);
+  }
+  DEBUG_IF_OK (comp->parent, err, "Released buffer %p to %s port %u: %s "
+      "(0x%08x)", buf, comp->name, port->index, gst_omx_error_to_string (err),
+      err);
+
+done:
+  gst_omx_component_handle_messages (comp);
+  g_mutex_unlock (&comp->lock);
+
+  return err;
+}
+
+/* NOTE: Must be called while holding comp->lock */
+static gboolean
+should_wait_until_flushed (GstOMXPort * port)
+{
+  if (!port->flushed)
+    /* Flush command hasn't been completed yet by OMX */
+    return TRUE;
+
+  if (port->buffers) {
+    guint i;
+
+    /* Wait for all the buffers used by OMX to be released */
+    for (i = 0; i < port->buffers->len; i++) {
+      GstOMXBuffer *buf = g_ptr_array_index (port->buffers, i);
+
+      if (buf->used)
+        return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_set_flushing (GstOMXPort * port, GstClockTime timeout,
+    gboolean flush)
+{
+  GstOMXComponent *comp;
+  OMX_ERRORTYPE err = OMX_ErrorNone;
+
+  g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+  comp = port->comp;
+
+  g_mutex_lock (&comp->lock);
+
+  GST_DEBUG_OBJECT (comp->parent, "Setting %s port %d to %sflushing",
+      comp->name, port->index, (flush ? "" : "not "));
+
+  gst_omx_component_handle_messages (comp);
+
+  if (flush == port->flushing) {
+    GST_DEBUG_OBJECT (comp->parent, "%s port %u was %sflushing already",
+        comp->name, port->index, (flush ? "" : "not "));
+    goto done;
+  }
+
+  if ((err = comp->last_error) != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (comp->parent, "Component %s is in error state: %s "
+        "(0x%08x)", comp->name, gst_omx_error_to_string (err), err);
+    goto done;
+  }
+
+  port->flushing = flush;
+  if (flush) {
+    gboolean signalled;
+    OMX_ERRORTYPE last_error;
+
+    gst_omx_component_send_message (comp, NULL);
+
+    /* Now flush the port */
+    port->flushed = FALSE;
+
+    err =
+        gst_omx_component_send_command (comp, OMX_CommandFlush, port->index,
+        NULL);
+
+    if (err != OMX_ErrorNone) {
+      GST_ERROR_OBJECT (comp->parent,
+          "Error sending flush command to %s port %u: %s (0x%08x)", comp->name,
+          port->index, gst_omx_error_to_string (err), err);
+      goto done;
+    }
+
+    if ((err = comp->last_error) != OMX_ErrorNone) {
+      GST_ERROR_OBJECT (comp->parent,
+          "Component %s is in error state: %s (0x%08x)", comp->name,
+          gst_omx_error_to_string (err), err);
+      goto done;
+    }
+
+    if (port->flushing != flush) {
+      GST_ERROR_OBJECT (comp->parent, "%s: another flush happened in the "
+          " meantime", comp->name);
+      goto done;
+    }
+
+    if (timeout == 0) {
+      if (should_wait_until_flushed (port))
+        err = OMX_ErrorTimeout;
+      goto done;
+    }
+
+    /* Retry until timeout or until an error happend or
+     * until all buffers were released by the component and
+     * the flush command completed */
+    signalled = TRUE;
+    last_error = OMX_ErrorNone;
+    gst_omx_component_handle_messages (comp);
+    while (should_wait_until_flushed (port)) {
+      signalled = gst_omx_component_wait_message (comp, timeout);
+      if (signalled)
+        gst_omx_component_handle_messages (comp);
+
+      last_error = comp->last_error;
+
+      if (!signalled || last_error != OMX_ErrorNone)
+        /* Something gone wrong or we timed out */
+        break;
+    }
+    port->flushed = FALSE;
+
+    GST_DEBUG_OBJECT (comp->parent, "%s port %d flushed", comp->name,
+        port->index);
+    if (last_error != OMX_ErrorNone) {
+      GST_ERROR_OBJECT (comp->parent,
+          "Got error while flushing %s port %u: %s (0x%08x)", comp->name,
+          port->index, gst_omx_error_to_string (last_error), last_error);
+      err = last_error;
+      goto done;
+    } else if (!signalled) {
+      GST_ERROR_OBJECT (comp->parent, "Timeout while flushing %s port %u",
+          comp->name, port->index);
+      err = OMX_ErrorTimeout;
+      goto done;
+    }
+  }
+
+  /* Reset EOS flag */
+  port->eos = FALSE;
+
+done:
+  gst_omx_port_update_port_definition (port, NULL);
+
+  DEBUG_IF_OK (comp->parent, err, "Set %s port %u to %sflushing: %s (0x%08x)",
+      comp->name, port->index, (flush ? "" : "not "),
+      gst_omx_error_to_string (err), err);
+  gst_omx_component_handle_messages (comp);
+  g_mutex_unlock (&comp->lock);
+
+  return err;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+gboolean
+gst_omx_port_is_flushing (GstOMXPort * port)
+{
+  GstOMXComponent *comp;
+  gboolean flushing;
+
+  g_return_val_if_fail (port != NULL, FALSE);
+
+  comp = port->comp;
+
+  g_mutex_lock (&comp->lock);
+  gst_omx_component_handle_messages (port->comp);
+  flushing = port->flushing;
+  g_mutex_unlock (&comp->lock);
+
+  GST_DEBUG_OBJECT (comp->parent, "%s port %u is flushing: %d", comp->name,
+      port->index, flushing);
+
+  return flushing;
+}
+
+static OMX_ERRORTYPE gst_omx_port_deallocate_buffers_unlocked (GstOMXPort *
+    port);
+
+/* NOTE: Must be called while holding comp->lock, uses comp->messages_lock */
+static OMX_ERRORTYPE
+gst_omx_port_allocate_buffers_unlocked (GstOMXPort * port,
+    const GList * buffers, const GList * images, guint n)
+{
+  GstOMXComponent *comp;
+  OMX_ERRORTYPE err = OMX_ErrorNone;
+  gint i;
+  const GList *l;
+
+  g_assert (!port->buffers || port->buffers->len == 0);
+
+  g_return_val_if_fail (!port->tunneled, OMX_ErrorBadParameter);
+
+  comp = port->comp;
+
+  gst_omx_component_handle_messages (port->comp);
+  if ((err = comp->last_error) != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
+        comp->name, gst_omx_error_to_string (err), err);
+    goto done;
+  }
+
+  /* Update the port definition to check if we need more
+   * buffers after the port configuration was done and to
+   * update the buffer size
+   */
+  gst_omx_port_update_port_definition (port, NULL);
+
+  g_return_val_if_fail (n != -1 || (!buffers
+          && !images), OMX_ErrorBadParameter);
+
+  if (n == -1)
+    n = port->port_def.nBufferCountActual;
+
+  g_return_val_if_fail (n == port->port_def.nBufferCountActual,
+      OMX_ErrorBadParameter);
+
+  GST_INFO_OBJECT (comp->parent,
+      "Allocating %d buffers of size %" G_GSIZE_FORMAT " for %s port %u", n,
+      (size_t) port->port_def.nBufferSize, comp->name, (guint) port->index);
+
+  if (!port->buffers)
+    port->buffers = g_ptr_array_sized_new (n);
+
+  l = (buffers ? buffers : images);
+  for (i = 0; i < n; i++) {
+    GstOMXBuffer *buf;
+
+    buf = g_slice_new0 (GstOMXBuffer);
+    buf->port = port;
+    buf->used = FALSE;
+    buf->settings_cookie = port->settings_cookie;
+    g_ptr_array_add (port->buffers, buf);
+
+    if (buffers) {
+      err =
+          OMX_UseBuffer (comp->handle, &buf->omx_buf, port->index, buf,
+          port->port_def.nBufferSize, l->data);
+      buf->eglimage = FALSE;
+    } else if (images) {
+      err =
+          OMX_UseEGLImage (comp->handle, &buf->omx_buf, port->index, buf,
+          l->data);
+      buf->eglimage = TRUE;
+    } else {
+      err =
+          OMX_AllocateBuffer (comp->handle, &buf->omx_buf, port->index, buf,
+          port->port_def.nBufferSize);
+      buf->eglimage = FALSE;
+    }
+
+    /* Let the caller decide to print an error when OMX_UseBuffer or
+     * OMX_UseEGLImage fail. Indeed it can be part of a trial path. So
+     * it is not necessary to warn the user if the fallback path succeeds.
+     */
+    if (err != OMX_ErrorNone) {
+      GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, (buffers
+              || images) ? GST_LEVEL_INFO : GST_LEVEL_ERROR, comp->parent,
+          "Failed to allocate buffer for %s port %u: %s (0x%08x)", comp->name,
+          port->index, gst_omx_error_to_string (err), err);
+      gst_omx_port_deallocate_buffers_unlocked (port);
+      goto done;
+    }
+
+    GST_DEBUG_OBJECT (comp->parent, "%s: allocated buffer %p (%p)",
+        comp->name, buf, buf->omx_buf->pBuffer);
+
+    g_assert (buf->omx_buf->pAppPrivate == buf);
+
+    /* In the beginning all buffers are not owned by the component */
+    g_queue_push_tail (&port->pending_buffers, buf);
+    if (buffers || images)
+      l = l->next;
+  }
+
+  gst_omx_component_handle_messages (comp);
+
+done:
+  gst_omx_port_update_port_definition (port, NULL);
+
+  INFO_IF_OK (comp->parent, err, "Allocated buffers for %s port %u: %s "
+      "(0x%08x)", comp->name, port->index, gst_omx_error_to_string (err), err);
+
+  return err;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_allocate_buffers (GstOMXPort * port)
+{
+  OMX_ERRORTYPE err;
+
+  g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+  g_mutex_lock (&port->comp->lock);
+  err = gst_omx_port_allocate_buffers_unlocked (port, NULL, NULL, -1);
+  port->allocation = GST_OMX_BUFFER_ALLOCATION_ALLOCATE_BUFFER;
+  g_mutex_unlock (&port->comp->lock);
+
+  return err;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_use_buffers (GstOMXPort * port, const GList * buffers)
+{
+  OMX_ERRORTYPE err;
+  guint n;
+
+  g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+  g_mutex_lock (&port->comp->lock);
+  n = g_list_length ((GList *) buffers);
+  err = gst_omx_port_allocate_buffers_unlocked (port, buffers, NULL, n);
+  port->allocation = GST_OMX_BUFFER_ALLOCATION_USE_BUFFER;
+  g_mutex_unlock (&port->comp->lock);
+
+  return err;
+}
+
+gboolean
+gst_omx_is_dynamic_allocation_supported (void)
+{
+  /* The Zynqultrascaleplus stack implements OMX 1.1.0 but supports the dynamic
+   * allocation mode from 1.2.0 as an extension. */
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+  return TRUE;
+#endif
+
+#if OMX_VERSION_MINOR == 2
+  return TRUE;
+#else
+  return FALSE;
+#endif
+}
+
+/* OMX 1.2.0 introduced a dynamic allocation mode where only buffer headers are
+ * being allocated during component's initialization. The actual buffers are
+ * allocated upstream and passed to OMX by setting the pBuffer dynamically
+ * for each input buffer.
+ *
+ * This function takes care of allocating the buffer headers. Element should
+ * then use one of the gst_omx_buffer_map_*() method to update buffer's pBuffer
+ * pointers for each incoming buffer.
+ *
+ * NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_use_dynamic_buffers (GstOMXPort * port)
+{
+  OMX_ERRORTYPE err;
+  GList *buffers = NULL;
+  guint i, n;
+
+  g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+  n = port->port_def.nBufferCountActual;
+  for (i = 0; i < port->port_def.nBufferCountActual; i++)
+    /* Pass NULL to UseBuffer() as the buffer is dynamic and so its payload
+     * will be set each time before being passed to OMX. */
+    buffers = g_list_prepend (buffers, GUINT_TO_POINTER (NULL));
+
+  g_mutex_lock (&port->comp->lock);
+  err = gst_omx_port_allocate_buffers_unlocked (port, buffers, NULL, n);
+  port->allocation = GST_OMX_BUFFER_ALLOCATION_USE_BUFFER_DYNAMIC;
+  g_mutex_unlock (&port->comp->lock);
+
+  g_list_free (buffers);
+
+  return err;
+}
+
+/* gst_omx_buffer_map_* methods are used in dynamic buffer mode to map
+ * a frame/memory/buffer and update @buffer so its pBuffer points to the
+ * mapped data. It also ensures that the input will stay alive until
+ * gst_omx_buffer_unmap() is called.
+ * This is used in OMX 1.2.0 dynamic allocation mode so an OMX component can
+ * safely process @buffer's content without having to copy it.
+ * The input will be automatically unmapped when @buffer is released by OMX.
+ */
+gboolean
+gst_omx_buffer_map_frame (GstOMXBuffer * buffer, GstBuffer * input,
+    GstVideoInfo * info)
+{
+  g_return_val_if_fail (buffer != NULL, FALSE);
+  g_return_val_if_fail (!buffer->input_frame_mapped, FALSE);
+  g_return_val_if_fail (!buffer->input_mem, FALSE);
+  g_return_val_if_fail (!buffer->input_buffer, FALSE);
+  g_return_val_if_fail (!buffer->input_buffer_mapped, FALSE);
+
+  if (!gst_video_frame_map (&buffer->input_frame, info, input, GST_MAP_READ))
+    return FALSE;
+
+  buffer->input_frame_mapped = TRUE;
+  buffer->omx_buf->pBuffer =
+      GST_VIDEO_FRAME_PLANE_DATA (&buffer->input_frame, 0);
+  buffer->omx_buf->nAllocLen = gst_buffer_get_size (input);
+  buffer->omx_buf->nFilledLen = buffer->omx_buf->nAllocLen;
+
+  return TRUE;
+}
+
+gboolean
+gst_omx_buffer_map_memory (GstOMXBuffer * buffer, GstMemory * mem)
+{
+  g_return_val_if_fail (buffer != NULL, FALSE);
+  g_return_val_if_fail (mem != NULL, FALSE);
+  g_return_val_if_fail (!buffer->input_frame_mapped, FALSE);
+  g_return_val_if_fail (!buffer->input_mem, FALSE);
+  g_return_val_if_fail (!buffer->input_buffer, FALSE);
+  g_return_val_if_fail (!buffer->input_buffer_mapped, FALSE);
+
+  if (!gst_memory_map (mem, &buffer->map, GST_MAP_READ))
+    return FALSE;
+
+  buffer->input_mem = gst_memory_ref (mem);
+  buffer->omx_buf->pBuffer = buffer->map.data;
+  buffer->omx_buf->nAllocLen = buffer->map.size;
+  buffer->omx_buf->nFilledLen = buffer->omx_buf->nAllocLen;
+
+  return TRUE;
+}
+
+gboolean
+gst_omx_buffer_import_fd (GstOMXBuffer * buffer, GstBuffer * input)
+{
+  gint fd;
+  GstMemory *mem;
+
+  g_return_val_if_fail (buffer != NULL, FALSE);
+  g_return_val_if_fail (input != NULL, FALSE);
+  g_return_val_if_fail (!buffer->input_frame_mapped, FALSE);
+  g_return_val_if_fail (!buffer->input_mem, FALSE);
+  g_return_val_if_fail (!buffer->input_buffer, FALSE);
+  g_return_val_if_fail (!buffer->input_buffer_mapped, FALSE);
+
+  mem = gst_buffer_peek_memory (input, 0);
+  g_return_val_if_fail (gst_is_dmabuf_memory (mem), FALSE);
+
+  fd = gst_dmabuf_memory_get_fd (mem);
+
+  buffer->input_buffer = gst_buffer_ref (input);
+  buffer->omx_buf->pBuffer = GUINT_TO_POINTER (fd);
+  buffer->omx_buf->nAllocLen = gst_memory_get_sizes (mem, NULL, NULL);
+  buffer->omx_buf->nFilledLen = buffer->omx_buf->nAllocLen;
+
+  return TRUE;
+}
+
+gboolean
+gst_omx_buffer_map_buffer (GstOMXBuffer * buffer, GstBuffer * input)
+{
+  g_return_val_if_fail (buffer != NULL, FALSE);
+  g_return_val_if_fail (input != NULL, FALSE);
+  g_return_val_if_fail (!buffer->input_frame_mapped, FALSE);
+  g_return_val_if_fail (!buffer->input_mem, FALSE);
+  g_return_val_if_fail (!buffer->input_buffer, FALSE);
+  g_return_val_if_fail (!buffer->input_buffer_mapped, FALSE);
+
+  if (!gst_buffer_map (input, &buffer->map, GST_MAP_READ))
+    return FALSE;
+
+  buffer->input_buffer_mapped = TRUE;
+  buffer->input_buffer = gst_buffer_ref (input);
+  buffer->omx_buf->pBuffer = buffer->map.data;
+  buffer->omx_buf->nAllocLen = buffer->map.size;
+  buffer->omx_buf->nFilledLen = buffer->omx_buf->nAllocLen;
+
+  return TRUE;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_use_eglimages (GstOMXPort * port, const GList * images)
+{
+  OMX_ERRORTYPE err;
+  guint n;
+
+  g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+  g_mutex_lock (&port->comp->lock);
+  n = g_list_length ((GList *) images);
+  err = gst_omx_port_allocate_buffers_unlocked (port, NULL, images, n);
+  g_mutex_unlock (&port->comp->lock);
+
+  return err;
+}
+
+/* NOTE: Must be called while holding comp->lock, uses comp->messages_lock */
+static OMX_ERRORTYPE
+gst_omx_port_deallocate_buffers_unlocked (GstOMXPort * port)
+{
+  GstOMXComponent *comp;
+  OMX_ERRORTYPE err = OMX_ErrorNone;
+  gint i, n;
+
+  g_return_val_if_fail (!port->tunneled, OMX_ErrorBadParameter);
+
+  comp = port->comp;
+
+  GST_INFO_OBJECT (comp->parent, "Deallocating buffers of %s port %u",
+      comp->name, port->index);
+
+  gst_omx_component_handle_messages (port->comp);
+
+  if (!port->buffers) {
+    GST_DEBUG_OBJECT (comp->parent, "No buffers allocated for %s port %u",
+        comp->name, port->index);
+    goto done;
+  }
+
+  if ((err = comp->last_error) != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
+        comp->name, gst_omx_error_to_string (err), err);
+    /* We still try to deallocate all buffers */
+  }
+
+  /* We only allow deallocation of buffers after they
+   * were all released from the port, either by flushing
+   * the port or by disabling it.
+   */
+  n = port->buffers->len;
+  for (i = 0; i < n; i++) {
+    GstOMXBuffer *buf = g_ptr_array_index (port->buffers, i);
+    OMX_ERRORTYPE tmp = OMX_ErrorNone;
+
+    if (buf->used) {
+      GST_ERROR_OBJECT (comp->parent, "Trying to free used buffer %p of %s "
+          "port %u", buf, comp->name, port->index);
+    }
+
+    /* omx_buf can be NULL if allocation failed earlier
+     * and we're just shutting down
+     *
+     * errors do not cause exiting this loop because we want
+     * to deallocate as much as possible.
+     */
+    if (buf->omx_buf) {
+      g_assert (buf == buf->omx_buf->pAppPrivate);
+      buf->omx_buf->pAppPrivate = NULL;
+      GST_DEBUG_OBJECT (comp->parent, "%s: deallocating buffer %p (%p)",
+          comp->name, buf, buf->omx_buf->pBuffer);
+
+      tmp = OMX_FreeBuffer (comp->handle, port->index, buf->omx_buf);
+
+      if (tmp != OMX_ErrorNone) {
+        GST_ERROR_OBJECT (comp->parent,
+            "Failed to deallocate buffer %d of %s port %u: %s (0x%08x)", i,
+            comp->name, port->index, gst_omx_error_to_string (tmp), tmp);
+        if (err == OMX_ErrorNone)
+          err = tmp;
+      }
+    }
+    g_slice_free (GstOMXBuffer, buf);
+  }
+  g_queue_clear (&port->pending_buffers);
+  g_ptr_array_unref (port->buffers);
+  port->buffers = NULL;
+
+  gst_omx_component_handle_messages (comp);
+
+done:
+  gst_omx_port_update_port_definition (port, NULL);
+
+  DEBUG_IF_OK (comp->parent, err, "Deallocated buffers of %s port %u: %s "
+      "(0x%08x)", comp->name, port->index, gst_omx_error_to_string (err), err);
+
+  return err;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_deallocate_buffers (GstOMXPort * port)
+{
+  OMX_ERRORTYPE err;
+
+  g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+  g_mutex_lock (&port->comp->lock);
+  err = gst_omx_port_deallocate_buffers_unlocked (port);
+  g_mutex_unlock (&port->comp->lock);
+
+  return err;
+}
+
+/* NOTE: Must be called while holding comp->lock, uses comp->messages_lock */
+static OMX_ERRORTYPE
+gst_omx_port_set_enabled_unlocked (GstOMXPort * port, gboolean enabled)
+{
+  GstOMXComponent *comp;
+  OMX_ERRORTYPE err = OMX_ErrorNone;
+
+  comp = port->comp;
+
+  gst_omx_component_handle_messages (comp);
+
+  if ((err = comp->last_error) != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
+        comp->name, gst_omx_error_to_string (err), err);
+    goto done;
+  }
+
+  if (port->enabled_pending || port->disabled_pending) {
+    GST_ERROR_OBJECT (comp->parent, "%s port %d enabled/disabled pending "
+        "already", comp->name, port->index);
+#if OMX_VERSION_MINOR == 2
+    err = OMX_ErrorBadParameter;
+#else
+    err = OMX_ErrorInvalidState;
+#endif
+    goto done;
+  }
+
+  GST_INFO_OBJECT (comp->parent, "Setting %s port %u to %s", comp->name,
+      port->index, (enabled ? "enabled" : "disabled"));
+
+  /* Check if the port is already enabled/disabled first */
+  gst_omx_port_update_port_definition (port, NULL);
+  if (! !port->port_def.bEnabled == ! !enabled)
+    goto done;
+
+  if (enabled)
+    port->enabled_pending = TRUE;
+  else
+    port->disabled_pending = TRUE;
+
+  if (enabled)
+    err =
+        gst_omx_component_send_command (comp, OMX_CommandPortEnable,
+        port->index, NULL);
+  else
+    err =
+        gst_omx_component_send_command (comp, OMX_CommandPortDisable,
+        port->index, NULL);
+
+  if (err != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (comp->parent,
+        "Failed to send enable/disable command to %s port %u: %s (0x%08x)",
+        comp->name, port->index, gst_omx_error_to_string (err), err);
+    goto done;
+  }
+
+  if ((err = comp->last_error) != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
+        comp->name, gst_omx_error_to_string (err), err);
+    goto done;
+  }
+
+done:
+  gst_omx_component_handle_messages (comp);
+
+  gst_omx_port_update_port_definition (port, NULL);
+
+  INFO_IF_OK (comp->parent, err, "Set %s port %u to %s%s: %s (0x%08x)",
+      comp->name, port->index, (err == OMX_ErrorNone ? "" : "not "),
+      (enabled ? "enabled" : "disabled"), gst_omx_error_to_string (err), err);
+
+  return err;
+}
+
+static OMX_ERRORTYPE
+gst_omx_port_wait_buffers_released_unlocked (GstOMXPort * port,
+    GstClockTime timeout)
+{
+  GstOMXComponent *comp;
+  OMX_ERRORTYPE err = OMX_ErrorNone;
+  OMX_ERRORTYPE last_error;
+  gboolean signalled;
+
+  comp = port->comp;
+
+  gst_omx_component_handle_messages (comp);
+
+  if ((err = comp->last_error) != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
+        comp->name, gst_omx_error_to_string (err), err);
+    goto done;
+  }
+
+  GST_INFO_OBJECT (comp->parent, "Waiting for %s port %u to release all "
+      "buffers", comp->name, port->index);
+
+  if (timeout == 0) {
+    if (!port->flushed || (port->buffers
+            && port->buffers->len >
+            g_queue_get_length (&port->pending_buffers)))
+      err = OMX_ErrorTimeout;
+    goto done;
+  }
+
+  /* Wait until all buffers are released by the port */
+  signalled = TRUE;
+  last_error = OMX_ErrorNone;
+  gst_omx_component_handle_messages (comp);
+  while (signalled && last_error == OMX_ErrorNone && (port->buffers
+          && port->buffers->len >
+          g_queue_get_length (&port->pending_buffers))) {
+    signalled = gst_omx_component_wait_message (comp, timeout);
+    if (signalled)
+      gst_omx_component_handle_messages (comp);
+    last_error = comp->last_error;
+  }
+
+  if (last_error != OMX_ErrorNone) {
+    err = last_error;
+    GST_ERROR_OBJECT (comp->parent,
+        "Got error while waiting for %s port %u to release all buffers: %s "
+        "(0x%08x)", comp->name, port->index, gst_omx_error_to_string (err),
+        err);
+    goto done;
+  } else if (!signalled) {
+    GST_ERROR_OBJECT (comp->parent, "Timeout waiting for %s port %u to "
+        "release all buffers", comp->name, port->index);
+    err = OMX_ErrorTimeout;
+    goto done;
+  }
+
+done:
+  gst_omx_component_handle_messages (comp);
+
+  gst_omx_port_update_port_definition (port, NULL);
+
+  DEBUG_IF_OK (comp->parent, err,
+      "Waited for %s port %u to release all buffers: %s (0x%08x)", comp->name,
+      port->index, gst_omx_error_to_string (err), err);
+
+  return err;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_wait_buffers_released (GstOMXPort * port, GstClockTime timeout)
+{
+  OMX_ERRORTYPE err;
+
+  g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+  g_mutex_lock (&port->comp->lock);
+  err = gst_omx_port_wait_buffers_released_unlocked (port, timeout);
+  g_mutex_unlock (&port->comp->lock);
+
+  return err;
+}
+
+void
+gst_omx_port_requeue_buffer (GstOMXPort * port, GstOMXBuffer * buf)
+{
+  g_mutex_lock (&port->comp->lock);
+  g_queue_push_tail (&port->pending_buffers, buf);
+  g_mutex_unlock (&port->comp->lock);
+
+  /* awake gst_omx_port_acquire_buffer() */
+  gst_omx_component_send_message (port->comp, NULL);
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_set_enabled (GstOMXPort * port, gboolean enabled)
+{
+  OMX_ERRORTYPE err;
+
+  g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+  g_mutex_lock (&port->comp->lock);
+  err = gst_omx_port_set_enabled_unlocked (port, enabled);
+  g_mutex_unlock (&port->comp->lock);
+
+  return err;
+}
+
+static OMX_ERRORTYPE
+gst_omx_port_populate_unlocked (GstOMXPort * port)
+{
+  GstOMXComponent *comp;
+  OMX_ERRORTYPE err = OMX_ErrorNone;
+  GstOMXBuffer *buf;
+
+  g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+  comp = port->comp;
+
+  GST_DEBUG_OBJECT (comp->parent, "Populating %s port %d", comp->name,
+      port->index);
+
+  gst_omx_component_handle_messages (comp);
+
+  if (port->flushing || port->disabled_pending || !port->port_def.bEnabled) {
+    GST_DEBUG_OBJECT (comp->parent, "%s port %u is flushing or disabled",
+        comp->name, port->index);
+    err = OMX_ErrorIncorrectStateOperation;
+    goto done;
+  }
+
+  if ((err = comp->last_error) != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (comp->parent, "Component %s is in error state: %s"
+        "(0x%08x)", comp->name, gst_omx_error_to_string (err), err);
+    goto done;
+  }
+
+  if (port->port_def.eDir == OMX_DirOutput && port->buffers && !port->tunneled) {
+    /* Enqueue all buffers for the component to fill */
+    while ((buf = g_queue_pop_head (&port->pending_buffers))) {
+      g_assert (!buf->used);
+
+      /* Reset all flags, some implementations don't
+       * reset them themselves and the flags are not
+       * valid anymore after the buffer was consumed.
+       * Also reset nFilledLen as FillThisBuffer() expects an empty buffer.
+       */
+      gst_omx_buffer_reset (buf);
+
+      log_omx_api_trace_buffer (comp, "FillThisBuffer", buf);
+      err = OMX_FillThisBuffer (comp->handle, buf->omx_buf);
+
+      if (err != OMX_ErrorNone) {
+        GST_ERROR_OBJECT (comp->parent,
+            "Failed to pass buffer %p (%p) to %s port %u: %s (0x%08x)", buf,
+            buf->omx_buf->pBuffer, comp->name, port->index,
+            gst_omx_error_to_string (err), err);
+        goto done;
+      }
+      GST_DEBUG_OBJECT (comp->parent, "Passed buffer %p (%p) to component %s",
+          buf, buf->omx_buf->pBuffer, comp->name);
+    }
+  }
+
+done:
+  gst_omx_port_update_port_definition (port, NULL);
+
+  DEBUG_IF_OK (comp->parent, err, "Populated %s port %u: %s (0x%08x)",
+      comp->name, port->index, gst_omx_error_to_string (err), err);
+  gst_omx_component_handle_messages (comp);
+
+  return err;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_populate (GstOMXPort * port)
+{
+  OMX_ERRORTYPE err;
+
+  g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+  g_mutex_lock (&port->comp->lock);
+  err = gst_omx_port_populate_unlocked (port);
+  g_mutex_unlock (&port->comp->lock);
+
+  return err;
+}
+
+/* NOTE: Must be called while holding comp->lock, uses comp->messages_lock */
+static OMX_ERRORTYPE
+gst_omx_port_wait_enabled_unlocked (GstOMXPort * port, GstClockTime timeout)
+{
+  GstOMXComponent *comp;
+  OMX_ERRORTYPE err = OMX_ErrorNone;
+  gboolean signalled;
+  OMX_ERRORTYPE last_error;
+  gboolean enabled;
+
+  comp = port->comp;
+
+  /* Check the current port status */
+  gst_omx_port_update_port_definition (port, NULL);
+
+  if (port->enabled_pending)
+    enabled = TRUE;
+  else if (port->disabled_pending)
+    enabled = FALSE;
+  else
+    enabled = port->port_def.bEnabled;
+
+  gst_omx_component_handle_messages (comp);
+
+  if ((err = comp->last_error) != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (comp->parent, "Component %s in error state: %s (0x%08x)",
+        comp->name, gst_omx_error_to_string (err), err);
+    goto done;
+  }
+
+  GST_INFO_OBJECT (comp->parent, "Waiting for %s port %u to be %s",
+      comp->name, port->index, (enabled ? "enabled" : "disabled"));
+
+  if (timeout == 0) {
+    if (port->enabled_pending || port->disabled_pending)
+      err = OMX_ErrorTimeout;
+    goto done;
+  }
+
+  /* And now wait until the enable/disable command is finished */
+  signalled = TRUE;
+  last_error = OMX_ErrorNone;
+  gst_omx_port_update_port_definition (port, NULL);
+  gst_omx_component_handle_messages (comp);
+  while (signalled && last_error == OMX_ErrorNone &&
+      (! !port->port_def.bEnabled != ! !enabled || port->enabled_pending
+          || port->disabled_pending)) {
+    signalled = gst_omx_component_wait_message (comp, timeout);
+    if (signalled)
+      gst_omx_component_handle_messages (comp);
+    last_error = comp->last_error;
+    gst_omx_port_update_port_definition (port, NULL);
+  }
+  port->enabled_pending = FALSE;
+  port->disabled_pending = FALSE;
+
+  if (!signalled) {
+    GST_ERROR_OBJECT (comp->parent,
+        "Timeout waiting for %s port %u to be %s", comp->name, port->index,
+        (enabled ? "enabled" : "disabled"));
+    err = OMX_ErrorTimeout;
+    goto done;
+  } else if (last_error != OMX_ErrorNone) {
+    GST_ERROR_OBJECT (comp->parent,
+        "Got error while waiting for %s port %u to be %s: %s (0x%08x)",
+        comp->name, port->index, (enabled ? "enabled" : "disabled"),
+        gst_omx_error_to_string (err), err);
+    err = last_error;
+  } else {
+    if (enabled) {
+      /* Reset EOS flag */
+      port->eos = FALSE;
+    }
+  }
+
+  gst_omx_component_handle_messages (comp);
+
+done:
+  gst_omx_port_update_port_definition (port, NULL);
+
+  GST_INFO_OBJECT (comp->parent, "%s port %u is %s%s: %s (0x%08x)", comp->name,
+      port->index, (err == OMX_ErrorNone ? "" : "not "),
+      (enabled ? "enabled" : "disabled"), gst_omx_error_to_string (err), err);
+
+  return err;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_wait_enabled (GstOMXPort * port, GstClockTime timeout)
+{
+  OMX_ERRORTYPE err;
+
+  g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+  g_mutex_lock (&port->comp->lock);
+  err = gst_omx_port_wait_enabled_unlocked (port, timeout);
+  g_mutex_unlock (&port->comp->lock);
+
+  return err;
+}
+
+gboolean
+gst_omx_port_is_enabled (GstOMXPort * port)
+{
+  gboolean enabled;
+
+  g_return_val_if_fail (port != NULL, FALSE);
+
+  gst_omx_port_update_port_definition (port, NULL);
+  enabled = ! !port->port_def.bEnabled;
+
+  GST_DEBUG_OBJECT (port->comp->parent, "%s port %u is enabled: %d",
+      port->comp->name, port->index, enabled);
+
+  return enabled;
+}
+
+/* NOTE: Uses comp->lock and comp->messages_lock */
+OMX_ERRORTYPE
+gst_omx_port_mark_reconfigured (GstOMXPort * port)
+{
+  GstOMXComponent *comp;
+  OMX_ERRORTYPE err = OMX_ErrorNone;
+
+  g_return_val_if_fail (port != NULL, OMX_ErrorUndefined);
+
+  comp = port->comp;
+
+  g_mutex_lock (&comp->lock);
+  GST_INFO_OBJECT (comp->parent, "Marking %s port %u is reconfigured",
+      comp->name, port->index);
+
+  gst_omx_component_handle_messages (comp);
+
+  if ((err = comp->last_error) != OMX_ErrorNone)
+    goto done;
+
+  port->configured_settings_cookie = port->settings_cookie;
+
+  if (port->port_def.eDir == OMX_DirOutput) {
+    GList *l;
+
+    for (l = comp->pending_reconfigure_outports; l; l = l->next) {
+      if (l->data == (gpointer) port) {
+        comp->pending_reconfigure_outports =
+            g_list_delete_link (comp->pending_reconfigure_outports, l);
+        break;
+      }
+    }
+    if (!comp->pending_reconfigure_outports)
+      gst_omx_component_send_message (comp, NULL);
+  }
+
+done:
+  gst_omx_port_update_port_definition (port, NULL);
+
+  INFO_IF_OK (comp->parent, err, "Marked %s port %u as reconfigured: %s "
+      "(0x%08x)", comp->name, port->index, gst_omx_error_to_string (err), err);
+
+  g_mutex_unlock (&comp->lock);
+
+  return err;
+}
+
+/* The OMX specs states that the nBufferCountActual of a port has to default
+ * to its nBufferCountMin. If we don't change nBufferCountActual we purely rely
+ * on this default. But in some cases, OMX may change nBufferCountMin before we
+ * allocate buffers. Like for example when configuring the input ports with the
+ * actual format, it may decrease the number of minimal buffers required.
+ * This method checks this and update nBufferCountActual if needed so we'll use
+ * less buffers than the worst case in such scenarios.
+ */
+gboolean
+gst_omx_port_ensure_buffer_count_actual (GstOMXPort * port, guint extra)
+{
+  OMX_PARAM_PORTDEFINITIONTYPE port_def;
+  guint nb;
+
+  gst_omx_port_get_port_definition (port, &port_def);
+
+  nb = port_def.nBufferCountMin + extra;
+  if (port_def.nBufferCountActual != nb) {
+    port_def.nBufferCountActual = nb;
+
+    GST_DEBUG_OBJECT (port->comp->parent,
+        "set port %d nBufferCountActual to %d", (guint) port->index, nb);
+
+    if (gst_omx_port_update_port_definition (port, &port_def) != OMX_ErrorNone)
+      return FALSE;
+  }
+
+  return TRUE;
+}
+
+gboolean
+gst_omx_port_update_buffer_count_actual (GstOMXPort * port, guint nb)
+{
+  OMX_PARAM_PORTDEFINITIONTYPE port_def;
+
+  gst_omx_port_get_port_definition (port, &port_def);
+
+  if (nb < port_def.nBufferCountMin) {
+    GST_DEBUG_OBJECT (port->comp->parent,
+        "Requested to use %d buffers on port %d but it's minimum is %d", nb,
+        (guint) port->index, (guint) port_def.nBufferCountMin);
+
+    nb = port_def.nBufferCountMin;
+  }
+
+  if (port_def.nBufferCountActual != nb) {
+    port_def.nBufferCountActual = nb;
+
+    GST_DEBUG_OBJECT (port->comp->parent,
+        "set port %d nBufferCountActual to %d", (guint) port->index, nb);
+
+    if (gst_omx_port_update_port_definition (port, &port_def) != OMX_ErrorNone)
+      return FALSE;
+  }
+
+  return TRUE;
+}
+
+gboolean
+gst_omx_port_set_dmabuf (GstOMXPort * port, gboolean dmabuf)
+{
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+  OMX_ALG_PORT_PARAM_BUFFER_MODE buffer_mode;
+  OMX_ERRORTYPE err;
+
+  GST_OMX_INIT_STRUCT (&buffer_mode);
+  buffer_mode.nPortIndex = port->index;
+
+  if (dmabuf)
+    buffer_mode.eMode = OMX_ALG_BUF_DMA;
+  else
+    buffer_mode.eMode = OMX_ALG_BUF_NORMAL;
+
+  err =
+      gst_omx_component_set_parameter (port->comp,
+      (OMX_INDEXTYPE) OMX_ALG_IndexPortParamBufferMode, &buffer_mode);
+  if (err != OMX_ErrorNone) {
+    GST_WARNING_OBJECT (port->comp->parent,
+        "Failed to set port %d in %sdmabuf mode: %s (0x%08x)",
+        port->index, dmabuf ? "" : "non-", gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  return TRUE;
+#else
+  /* dmabuf not supported for this platform */
+  return FALSE;
+#endif
+}
+
+gboolean
+gst_omx_port_set_subframe (GstOMXPort * port, gboolean enabled)
+{
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+  OMX_ALG_VIDEO_PARAM_SUBFRAME subframe_mode;
+  OMX_ERRORTYPE err;
+  GST_DEBUG_OBJECT (port->comp->parent, "%s subframe mode for Zynq",
+      enabled ? "Enable" : "Disable");
+  GST_OMX_INIT_STRUCT (&subframe_mode);
+  subframe_mode.nPortIndex = port->index;
+
+  subframe_mode.bEnableSubframe = enabled;
+
+  err = gst_omx_component_set_parameter (port->comp,
+      (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoSubframe, &subframe_mode);
+  if (err != OMX_ErrorNone) {
+    GST_WARNING_OBJECT (port->comp->parent,
+        "Failed to %s subframe mode on port %d: %s (0x%08x)",
+        enabled ? "enable" : "disable", port->index,
+        gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  return TRUE;
+#else
+  /* subframe mode is not supported on this platform */
+  return FALSE;
+#endif
+}
+
+gboolean
+gst_omx_port_get_subframe (GstOMXPort * port)
+{
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+  OMX_ALG_VIDEO_PARAM_SUBFRAME subframe_mode;
+  OMX_ERRORTYPE err;
+
+  GST_OMX_INIT_STRUCT (&subframe_mode);
+  subframe_mode.nPortIndex = port->index;
+
+  err = gst_omx_component_get_parameter (port->comp,
+      (OMX_INDEXTYPE) OMX_ALG_IndexParamVideoSubframe, &subframe_mode);
+  if (err != OMX_ErrorNone) {
+    GST_WARNING_OBJECT (port->comp->parent,
+        "Failed to get subframe mode on port %d: %s (0x%08x)",
+        port->index, gst_omx_error_to_string (err), err);
+    return FALSE;
+  }
+
+  return subframe_mode.bEnableSubframe;
+#else
+  /* subframe mode is not supported on this platform */
+  return FALSE;
+#endif
+}
+
+typedef GType (*GGetTypeFunction) (void);
+
+static const GGetTypeFunction types[] = {
+  gst_omx_analog_audio_sink_get_type, gst_omx_hdmi_audio_sink_get_type,
+  gst_omx_mpeg2_video_dec_get_type, gst_omx_mpeg4_video_dec_get_type,
+  gst_omx_h264_dec_get_type, gst_omx_h263_dec_get_type,
+  gst_omx_wmv_dec_get_type, gst_omx_mpeg4_video_enc_get_type,
+  gst_omx_h264_enc_get_type, gst_omx_h263_enc_get_type,
+  gst_omx_aac_enc_get_type, gst_omx_mjpeg_dec_get_type,
+  gst_omx_aac_dec_get_type, gst_omx_mp3_dec_get_type,
+  gst_omx_aac_dec_get_type, gst_omx_mp3_enc_get_type,
+  gst_omx_amr_dec_get_type
+#ifdef HAVE_VP8
+      , gst_omx_vp8_dec_get_type
+#endif
+#ifdef HAVE_THEORA
+      , gst_omx_theora_dec_get_type
+#endif
+#ifdef HAVE_HEVC
+      , gst_omx_h265_enc_get_type, gst_omx_h265_dec_get_type
+#endif
+};
+
+struct TypeOffest
+{
+  GType (*get_type) (void);
+  glong offset;
+};
+
+static const struct TypeOffest base_types[] = {
+  {gst_omx_audio_sink_get_type, G_STRUCT_OFFSET (GstOMXAudioSinkClass, cdata)},
+  {gst_omx_video_dec_get_type, G_STRUCT_OFFSET (GstOMXVideoDecClass, cdata)},
+  {gst_omx_video_enc_get_type, G_STRUCT_OFFSET (GstOMXVideoEncClass, cdata)},
+  {gst_omx_audio_dec_get_type, G_STRUCT_OFFSET (GstOMXAudioDecClass, cdata)},
+  {gst_omx_audio_enc_get_type, G_STRUCT_OFFSET (GstOMXAudioEncClass, cdata)},
+};
+
+static GKeyFile *config = NULL;
+GKeyFile *
+gst_omx_get_configuration (void)
+{
+  return config;
+}
+
+const gchar *
+gst_omx_error_to_string (OMX_ERRORTYPE err)
+{
+  guint err_u = (guint) err;
+
+  switch (err_u) {
+    case OMX_ErrorNone:
+      return "None";
+    case OMX_ErrorInsufficientResources:
+      return "Insufficient resources";
+    case OMX_ErrorUndefined:
+      return "Undefined";
+    case OMX_ErrorInvalidComponentName:
+      return "Invalid component name";
+    case OMX_ErrorComponentNotFound:
+      return "Component not found";
+    case OMX_ErrorBadParameter:
+      return "Bad parameter";
+    case OMX_ErrorNotImplemented:
+      return "Not implemented";
+    case OMX_ErrorUnderflow:
+      return "Underflow";
+    case OMX_ErrorOverflow:
+      return "Overflow";
+    case OMX_ErrorHardware:
+      return "Hardware";
+    case OMX_ErrorStreamCorrupt:
+      return "Stream corrupt";
+    case OMX_ErrorPortsNotCompatible:
+      return "Ports not compatible";
+    case OMX_ErrorResourcesLost:
+      return "Resources lost";
+    case OMX_ErrorNoMore:
+      return "No more";
+    case OMX_ErrorVersionMismatch:
+      return "Version mismatch";
+    case OMX_ErrorNotReady:
+      return "Not ready";
+    case OMX_ErrorTimeout:
+      return "Timeout";
+    case OMX_ErrorSameState:
+      return "Same state";
+    case OMX_ErrorResourcesPreempted:
+      return "Resources preempted";
+    case OMX_ErrorIncorrectStateTransition:
+      return "Incorrect state transition";
+    case OMX_ErrorIncorrectStateOperation:
+      return "Incorrect state operation";
+    case OMX_ErrorUnsupportedSetting:
+      return "Unsupported setting";
+    case OMX_ErrorUnsupportedIndex:
+      return "Unsupported index";
+    case OMX_ErrorBadPortIndex:
+      return "Bad port index";
+    case OMX_ErrorPortUnpopulated:
+      return "Port unpopulated";
+    case OMX_ErrorComponentSuspended:
+      return "Component suspended";
+    case OMX_ErrorDynamicResourcesUnavailable:
+      return "Dynamic resources unavailable";
+    case OMX_ErrorMbErrorsInFrame:
+      return "Macroblock errors in frame";
+    case OMX_ErrorFormatNotDetected:
+      return "Format not detected";
+    case OMX_ErrorSeperateTablesUsed:
+      return "Separate tables used";
+    case OMX_ErrorTunnelingUnsupported:
+      return "Tunneling unsupported";
+#if OMX_VERSION_MINOR == 1
+    case OMX_ErrorInvalidComponent:
+      return "Invalid component";
+    case OMX_ErrorInvalidState:
+      return "Invalid state";
+    case OMX_ErrorPortUnresponsiveDuringAllocation:
+      return "Port unresponsive during allocation";
+    case OMX_ErrorPortUnresponsiveDuringDeallocation:
+      return "Port unresponsive during deallocation";
+    case OMX_ErrorPortUnresponsiveDuringStop:
+      return "Port unresponsive during stop";
+    case OMX_ErrorContentPipeOpenFailed:
+      return "Content pipe open failed";
+    case OMX_ErrorContentPipeCreationFailed:
+      return "Content pipe creation failed";
+#endif
+    default:
+      if (err_u >= (guint) OMX_ErrorKhronosExtensions
+          && err_u < (guint) OMX_ErrorVendorStartUnused) {
+        return "Khronos extension error";
+      } else if (err_u >= (guint) OMX_ErrorVendorStartUnused
+          && err_u < (guint) OMX_ErrorMax) {
+        return "Vendor specific error";
+      } else {
+        return "Unknown error";
+      }
+  }
+}
+
+const gchar *
+gst_omx_state_to_string (OMX_STATETYPE state)
+{
+  switch (state) {
+    case OMX_StateInvalid:
+      return "Invalid";
+    case OMX_StateLoaded:
+      return "Loaded";
+    case OMX_StateIdle:
+      return "Idle";
+    case OMX_StateExecuting:
+      return "Executing";
+    case OMX_StatePause:
+      return "Pause";
+    case OMX_StateWaitForResources:
+      return "WaitForResources";
+    default:
+      if (state >= OMX_StateKhronosExtensions
+          && state < OMX_StateVendorStartUnused)
+        return "KhronosExtensionState";
+      else if (state >= OMX_StateVendorStartUnused && state < OMX_StateMax)
+        return "CustomVendorState";
+      break;
+  }
+  return "Unknown state";
+}
+
+const gchar *
+gst_omx_command_to_string (OMX_COMMANDTYPE cmd)
+{
+  switch (cmd) {
+    case OMX_CommandStateSet:
+      return "SetState";
+    case OMX_CommandFlush:
+      return "Flush";
+    case OMX_CommandPortDisable:
+      return "DisablePort";
+    case OMX_CommandPortEnable:
+      return "EnablePort";
+    case OMX_CommandMarkBuffer:
+      return "MarkBuffer";
+    default:
+      if (cmd >= OMX_CommandKhronosExtensions
+          && cmd < OMX_CommandVendorStartUnused)
+        return "KhronosExtensionCommand";
+      if (cmd >= OMX_CommandVendorStartUnused && cmd < OMX_CommandMax)
+        return "VendorExtensionCommand";
+      break;
+  }
+  return "Unknown command";
+}
+
+struct BufferFlagString
+{
+  guint32 flag;
+  const gchar *str;
+};
+
+struct BufferFlagString buffer_flags_map[] = {
+  {OMX_BUFFERFLAG_EOS, "eos"},
+  {OMX_BUFFERFLAG_STARTTIME, "start-time"},
+  {OMX_BUFFERFLAG_DECODEONLY, "decode-only"},
+  {OMX_BUFFERFLAG_DATACORRUPT, "data-corrupt"},
+  {OMX_BUFFERFLAG_ENDOFFRAME, "end-of-frame"},
+  {OMX_BUFFERFLAG_SYNCFRAME, "sync-frame"},
+  {OMX_BUFFERFLAG_EXTRADATA, "extra-data"},
+  {OMX_BUFFERFLAG_CODECCONFIG, "codec-config"},
+  /* Introduced in OMX 1.2.0 */
+#ifdef OMX_BUFFERFLAG_TIMESTAMPINVALID
+  {OMX_BUFFERFLAG_TIMESTAMPINVALID, "timestamp-invalid"},
+#endif
+#ifdef OMX_BUFFERFLAG_READONLY
+  {OMX_BUFFERFLAG_READONLY, "read-only"},
+#endif
+#ifdef OMX_BUFFERFLAG_ENDOFSUBFRAME
+  {OMX_BUFFERFLAG_ENDOFSUBFRAME, "end-of-subframe"},
+#endif
+#ifdef OMX_BUFFERFLAG_SKIPFRAME
+  {OMX_BUFFERFLAG_SKIPFRAME, "skip-frame"},
+#endif
+#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
+  {OMX_ALG_BUFFERFLAG_TOP_FIELD, "top-field"},
+  {OMX_ALG_BUFFERFLAG_BOT_FIELD, "bottom-field"},
+#endif
+  {0, NULL},
+};
+
+
+const gchar *
+gst_omx_buffer_flags_to_string (guint32 flags)
+{
+  GString *s = NULL;
+  guint i;
+  const gchar *str;
+
+  if (flags == 0)
+    return "";
+
+  /* Keep a cache of the string representation of the flags so we don't allocate
+   * and free strings for each buffer. In practice we should only have a handfull
+   * of flags so the cache won't consume much memory. */
+  if (!buffer_flags_str) {
+    G_LOCK (buffer_flags_str);
+    buffer_flags_str = g_hash_table_new_full (NULL, NULL, NULL, g_free);
+    G_UNLOCK (buffer_flags_str);
+  }
+
+  str = g_hash_table_lookup (buffer_flags_str, GUINT_TO_POINTER (flags));
+  if (str)
+    return str;
+
+  for (i = 0; buffer_flags_map[i].str != NULL; i++) {
+    if ((flags & buffer_flags_map[i].flag) == 0)
+      continue;
+
+    if (!s)
+      s = g_string_new (buffer_flags_map[i].str);
+    else
+      g_string_append_printf (s, ", %s", buffer_flags_map[i].str);
+  }
+
+  if (!s)
+    return "<unknown>";
+
+  str = g_string_free (s, FALSE);
+
+  G_LOCK (buffer_flags_str);
+  /* Transfer ownership of str to hash table */
+  g_hash_table_insert (buffer_flags_str, GUINT_TO_POINTER (flags),
+      (gchar *) str);
+  G_UNLOCK (buffer_flags_str);
+
+  return str;
+}
+
+#if defined(USE_OMX_TARGET_RPI)
+#define DEFAULT_HACKS (GST_OMX_HACK_NO_COMPONENT_ROLE | GST_OMX_HACK_HEIGHT_MULTIPLE_16)
+#else
+#define DEFAULT_HACKS (0)
+#endif
+
+guint64
+gst_omx_parse_hacks (gchar ** hacks)
+{
+  guint64 hacks_flags = DEFAULT_HACKS;
+
+  if (!hacks)
+    return 0;
+
+  while (*hacks) {
+    if (g_str_equal (*hacks,
+            "event-port-settings-changed-ndata-parameter-swap"))
+      hacks_flags |=
+          GST_OMX_HACK_EVENT_PORT_SETTINGS_CHANGED_NDATA_PARAMETER_SWAP;
+    else if (g_str_equal (*hacks, "event-port-settings-changed-port-0-to-1"))
+      hacks_flags |= GST_OMX_HACK_EVENT_PORT_SETTINGS_CHANGED_PORT_0_TO_1;
+    else if (g_str_equal (*hacks, "video-framerate-integer"))
+      hacks_flags |= GST_OMX_HACK_VIDEO_FRAMERATE_INTEGER;
+    else if (g_str_equal (*hacks, "syncframe-flag-not-used"))
+      hacks_flags |= GST_OMX_HACK_SYNCFRAME_FLAG_NOT_USED;
+    else if (g_str_equal (*hacks, "no-component-reconfigure"))
+      hacks_flags |= GST_OMX_HACK_NO_COMPONENT_RECONFIGURE;
+    else if (g_str_equal (*hacks, "no-empty-eos-buffer"))
+      hacks_flags |= GST_OMX_HACK_NO_EMPTY_EOS_BUFFER;
+    else if (g_str_equal (*hacks, "drain-may-not-return"))
+      hacks_flags |= GST_OMX_HACK_DRAIN_MAY_NOT_RETURN;
+    else if (g_str_equal (*hacks, "no-component-role"))
+      hacks_flags |= GST_OMX_HACK_NO_COMPONENT_ROLE;
+    else if (g_str_equal (*hacks, "no-disable-outport"))
+      hacks_flags |= GST_OMX_HACK_NO_DISABLE_OUTPORT;
+    else if (g_str_equal (*hacks, "signals-premature-eos"))
+      hacks_flags |= GST_OMX_HACK_SIGNALS_PREMATURE_EOS;
+    else if (g_str_equal (*hacks, "height-multiple-16"))
+      hacks_flags |= GST_OMX_HACK_HEIGHT_MULTIPLE_16;
+    else if (g_str_equal (*hacks, "pass-profile-to-decoder"))
+      hacks_flags |= GST_OMX_HACK_PASS_PROFILE_TO_DECODER;
+    else if (g_str_equal (*hacks, "pass-color-format-to-decoder"))
+      hacks_flags |= GST_OMX_HACK_PASS_COLOR_FORMAT_TO_DECODER;
+    else if (g_str_equal (*hacks, "ensure-buffer-count-actual"))
+      hacks_flags |= GST_OMX_HACK_ENSURE_BUFFER_COUNT_ACTUAL;
+    else
+      GST_WARNING ("Unknown hack: %s", *hacks);
+    hacks++;
+  }
+
+  return hacks_flags;
+}
+
+
+void
+gst_omx_set_default_role (GstOMXClassData * class_data,
+    const gchar * default_role)
+{
+  if (!class_data->component_role)
+    class_data->component_role = default_role;
+}
+
+static void
+_class_init (gpointer g_class, gpointer data)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+  GstOMXClassData *class_data = NULL;
+  GKeyFile *config;
+  const gchar *element_name = data;
+  GError *err;
+  gchar *core_name, *component_name, *component_role;
+  gint in_port_index, out_port_index;
+  gchar *template_caps;
+  GstPadTemplate *templ;
+  GstCaps *caps;
+  gchar **hacks;
+  int i;
+
+  if (!element_name)
+    return;
+
+  /* Find the GstOMXClassData for this class */
+  for (i = 0; i < G_N_ELEMENTS (base_types); i++) {
+    GType gtype = base_types[i].get_type ();
+
+    if (G_TYPE_CHECK_CLASS_TYPE (g_class, gtype)) {
+      class_data = (GstOMXClassData *)
+          (((guint8 *) g_class) + base_types[i].offset);
+      break;
+    }
+  }
+
+  g_assert (class_data != NULL);
+
+  config = gst_omx_get_configuration ();
+
+  /* This will alwaxys succeed, see check in plugin_init */
+  core_name = g_key_file_get_string (config, element_name, "core-name", NULL);
+  g_assert (core_name != NULL);
+  class_data->core_name = core_name;
+  component_name =
+      g_key_file_get_string (config, element_name, "component-name", NULL);
+  g_assert (component_name != NULL);
+  class_data->component_name = component_name;
+
+  /* If this fails we simply don't set a role */
+  if ((component_role =
+          g_key_file_get_string (config, element_name, "component-role",
+              NULL))) {
+    GST_DEBUG ("Using component-role '%s' for element '%s'", component_role,
+        element_name);
+    class_data->component_role = component_role;
+  }
+
+
+  /* Now set the inport/outport indizes and assume sane defaults */
+  err = NULL;
+  in_port_index =
+      g_key_file_get_integer (config, element_name, "in-port-index", &err);
+  if (err != NULL) {
+    GST_DEBUG ("No 'in-port-index' set for element '%s', auto-detecting: %s",
+        element_name, err->message);
+    in_port_index = -1;
+    g_error_free (err);
+  }
+  class_data->in_port_index = in_port_index;
+
+  err = NULL;
+  out_port_index =
+      g_key_file_get_integer (config, element_name, "out-port-index", &err);
+  if (err != NULL) {
+    GST_DEBUG ("No 'out-port-index' set for element '%s', auto-detecting: %s",
+        element_name, err->message);
+    out_port_index = -1;
+    g_error_free (err);
+  }
+  class_data->out_port_index = out_port_index;
+
+  /* Add pad templates */
+  err = NULL;
+  if (class_data->type != GST_OMX_COMPONENT_TYPE_SOURCE) {
+    if (!(template_caps =
+            g_key_file_get_string (config, element_name, "sink-template-caps",
+                &err))) {
+      GST_DEBUG
+          ("No sink template caps specified for element '%s', using default '%s'",
+          element_name, class_data->default_sink_template_caps);
+      caps = gst_caps_from_string (class_data->default_sink_template_caps);
+      g_assert (caps != NULL);
+      g_error_free (err);
+    } else {
+      caps = gst_caps_from_string (template_caps);
+      if (!caps) {
+        GST_DEBUG
+            ("Could not parse sink template caps '%s' for element '%s', using default '%s'",
+            template_caps, element_name,
+            class_data->default_sink_template_caps);
+        caps = gst_caps_from_string (class_data->default_sink_template_caps);
+        g_assert (caps != NULL);
+      }
+    }
+    templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps);
+    g_free (template_caps);
+    gst_element_class_add_pad_template (element_class, templ);
+    gst_caps_unref (caps);
+  }
+
+  err = NULL;
+  if (class_data->type != GST_OMX_COMPONENT_TYPE_SINK) {
+    if (!(template_caps =
+            g_key_file_get_string (config, element_name, "src-template-caps",
+                &err))) {
+      GST_DEBUG
+          ("No src template caps specified for element '%s', using default '%s'",
+          element_name, class_data->default_src_template_caps);
+      caps = gst_caps_from_string (class_data->default_src_template_caps);
+      g_assert (caps != NULL);
+      g_error_free (err);
+    } else {
+      caps = gst_caps_from_string (template_caps);
+      if (!caps) {
+        GST_DEBUG
+            ("Could not parse src template caps '%s' for element '%s', using default '%s'",
+            template_caps, element_name, class_data->default_src_template_caps);
+        caps = gst_caps_from_string (class_data->default_src_template_caps);
+        g_assert (caps != NULL);
+      }
+    }
+    templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps);
+    g_free (template_caps);
+    gst_element_class_add_pad_template (element_class, templ);
+    gst_caps_unref (caps);
+  }
+
+  if ((hacks =
+          g_key_file_get_string_list (config, element_name, "hacks", NULL,
+              NULL))) {
+#ifndef GST_DISABLE_GST_DEBUG
+    gchar **walk = hacks;
+
+    while (*walk) {
+      GST_DEBUG ("Using hack: %s", *walk);
+      walk++;
+    }
+#endif
+
+    class_data->hacks = gst_omx_parse_hacks (hacks);
+    g_strfreev (hacks);
+  }
+}
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+  GError *err = NULL;
+  gchar **config_dirs;
+  gchar **elements;
+  gchar *env_config_dir;
+  const gchar *user_config_dir;
+  const gchar *const *system_config_dirs;
+  gint i, j;
+  gsize n_elements;
+  static const gchar *config_name[] = { "gstomx.conf", NULL };
+  static const gchar *env_config_name[] = { "GST_OMX_CONFIG_DIR", NULL };
+  static const gchar *gst_omx_config_dir = GST_OMX_CONFIG_DIR;
+
+  GST_DEBUG_CATEGORY_INIT (gstomx_debug, "omx", 0, "gst-omx");
+  GST_DEBUG_CATEGORY_INIT (gst_omx_video_debug_category, "omxvideo", 0,
+      "gst-omx-video");
+  GST_DEBUG_CATEGORY_INIT (OMX_API_TRACE, "OMX_API_TRACE", 0,
+      "gst-omx performace");
+
+  /* Read configuration file gstomx.conf from the preferred
+   * configuration directories */
+  env_config_dir = g_strdup (g_getenv (*env_config_name));
+  user_config_dir = g_get_user_config_dir ();
+  system_config_dirs = g_get_system_config_dirs ();
+  config_dirs =
+      g_new (gchar *, g_strv_length ((gchar **) system_config_dirs) + 4);
+
+  i = 0;
+  j = 0;
+  if (env_config_dir)
+    config_dirs[i++] = (gchar *) env_config_dir;
+  config_dirs[i++] = (gchar *) user_config_dir;
+  while (system_config_dirs[j])
+    config_dirs[i++] = (gchar *) system_config_dirs[j++];
+  config_dirs[i++] = (gchar *) gst_omx_config_dir;
+  config_dirs[i++] = NULL;
+
+  gst_plugin_add_dependency (plugin, env_config_name,
+      (const gchar **) (config_dirs + (env_config_dir ? 1 : 0)), config_name,
+      GST_PLUGIN_DEPENDENCY_FLAG_NONE);
+
+  config = g_key_file_new ();
+  if (!g_key_file_load_from_dirs (config, *config_name,
+          (const gchar **) config_dirs, NULL, G_KEY_FILE_NONE, &err)) {
+#ifdef USE_OMX_TARGET_GENERIC
+    GST_INFO ("No configuration file found; "
+        "ignore as gst-omx has been built with the generic target used only for testing");
+#else
+    {
+      gchar *paths;
+
+      paths = g_strjoinv (":", config_dirs);
+      GST_ERROR
+          ("Failed to load configuration file: %s (searched in: %s as per "
+          "GST_OMX_CONFIG_DIR environment variable, the xdg user config "
+          "directory (or XDG_CONFIG_HOME) and the system config directory "
+          "(or XDG_CONFIG_DIRS)", err->message, paths);
+      g_free (paths);
+    }
+#endif /* USE_OMX_TARGET_GENERIC */
+
+    g_error_free (err);
+    goto done;
+  }
+
+  /* Initialize all types */
+  for (i = 0; i < G_N_ELEMENTS (types); i++)
+    types[i] ();
+
+  elements = g_key_file_get_groups (config, &n_elements);
+  for (i = 0; i < n_elements; i++) {
+    GTypeQuery type_query;
+    GTypeInfo type_info = { 0, };
+    GType type, subtype;
+    gchar *type_name, *core_name, *component_name;
+    gint rank;
+
+    GST_DEBUG ("Registering element '%s'", elements[i]);
+
+    err = NULL;
+    if (!(type_name =
+            g_key_file_get_string (config, elements[i], "type-name", &err))) {
+      GST_ERROR
+          ("Unable to read 'type-name' configuration for element '%s': %s",
+          elements[i], err->message);
+      g_error_free (err);
+      continue;
+    }
+
+    type = g_type_from_name (type_name);
+    if (type == G_TYPE_INVALID) {
+      GST_ERROR ("Invalid type name '%s' for element '%s'", type_name,
+          elements[i]);
+      g_free (type_name);
+      continue;
+    }
+    if (!g_type_is_a (type, GST_TYPE_ELEMENT)) {
+      GST_ERROR ("Type '%s' is no GstElement subtype for element '%s'",
+          type_name, elements[i]);
+      g_free (type_name);
+      continue;
+    }
+    g_free (type_name);
+
+    /* And now some sanity checking */
+    err = NULL;
+    if (!(core_name =
+            g_key_file_get_string (config, elements[i], "core-name", &err))) {
+      GST_ERROR
+          ("Unable to read 'core-name' configuration for element '%s': %s",
+          elements[i], err->message);
+      g_error_free (err);
+      continue;
+    }
+    if (!g_file_test (core_name, G_FILE_TEST_IS_REGULAR)) {
+      GST_ERROR ("Core '%s' does not exist for element '%s'", core_name,
+          elements[i]);
+      g_free (core_name);
+      continue;
+    }
+    g_free (core_name);
+
+    err = NULL;
+    if (!(component_name =
+            g_key_file_get_string (config, elements[i], "component-name",
+                &err))) {
+      GST_ERROR
+          ("Unable to read 'component-name' configuration for element '%s': %s",
+          elements[i], err->message);
+      g_error_free (err);
+      continue;
+    }
+    g_free (component_name);
+
+    err = NULL;
+    rank = g_key_file_get_integer (config, elements[i], "rank", &err);
+    if (err != NULL) {
+      GST_ERROR ("No rank set for element '%s': %s", elements[i], err->message);
+      g_error_free (err);
+      continue;
+    }
+
+    /* And now register the type, all other configuration will
+     * be handled by the type itself */
+    g_type_query (type, &type_query);
+    memset (&type_info, 0, sizeof (type_info));
+    type_info.class_size = type_query.class_size;
+    type_info.instance_size = type_query.instance_size;
+    type_info.class_init = _class_init;
+    type_info.class_data = g_strdup (elements[i]);
+    type_name = g_strdup_printf ("%s-%s", g_type_name (type), elements[i]);
+    if (g_type_from_name (type_name) != G_TYPE_INVALID) {
+      GST_ERROR ("Type '%s' already exists for element '%s'", type_name,
+          elements[i]);
+      g_free (type_name);
+      continue;
+    }
+    subtype = g_type_register_static (type, type_name, &type_info, 0);
+    g_free (type_name);
+    gst_element_register (plugin, elements[i], rank, subtype);
+  }
+  g_strfreev (elements);
+
+done:
+  g_free (env_config_dir);
+  g_free (config_dirs);
+
+  return TRUE;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    omx,
+    "GStreamer OpenMAX Plug-ins",
+    plugin_init,
+    PACKAGE_VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --git a/omx/gstomx.h b/omx/gstomx.h
index 6862463..718f044 100644
--- a/omx/gstomx.h
+++ b/omx/gstomx.h
@@ -27,6 +27,7 @@
 #include <gst/gst.h>
 #include <gst/video/video.h>
 #include <string.h>
+#include <stdint.h>
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -53,6 +54,7 @@
 
 #include <OMX_Core.h>
 #include <OMX_Component.h>
+#include <OMX_Types.h>
 
 #ifdef USE_OMX_TARGET_RPI
 #include <OMX_Broadcom.h>
@@ -230,6 +232,25 @@ typedef enum {
   GST_OMX_ACQUIRE_BUFFER_NO_AVAILABLE,
 } GstOMXAcquireBufferReturn;
 
+/*AW Private */
+typedef struct OmxPrivateBuffer {
+    uint64_t       nID;
+    unsigned int   nFlag;
+    unsigned char* pAddrPhyY;
+    unsigned char* pAddrPhyC;
+    unsigned char* pAddrVirY;
+    unsigned char* pAddrVirC;
+    int            bEnableCrop;
+    int            nLeft;
+    int            nTop;
+    int            nWidth;
+    int            nHeight;
+    int            nShareBufFd;
+    //for get-omx
+    int            nBufferSize;
+    void*          gstFrame;
+}OmxPrivateBuffer;
+
 struct _GstOMXCore {
   /* Handle to the OpenMAX IL core shared library */
   GModule *module;
diff --git a/omx/gstomxallocator.c b/omx/gstomxallocator.c
index a180669..10fad30 100644
--- a/omx/gstomxallocator.c
+++ b/omx/gstomxallocator.c
@@ -494,7 +494,8 @@ gst_omx_allocator_allocate (GstOMXAllocator * allocator, gint index,
       break;
     case GST_OMX_ALLOCATOR_FOREIGN_MEM_DMABUF:
     {
-      gint fd = GPOINTER_TO_INT (omx_buf->omx_buf->pBuffer);
+      OmxPrivateBuffer *sOmxOutPrivateBuffer = (OmxPrivateBuffer*)(omx_buf->omx_buf->pBuffer);
+      gint fd = sOmxOutPrivateBuffer->nShareBufFd;
       mem->foreign_mem =
           gst_dmabuf_allocator_alloc (allocator->foreign_allocator, fd,
           omx_buf->omx_buf->nAllocLen);
diff --git a/omx/gstomxavsdec.c b/omx/gstomxavsdec.c
new file mode 100644
index 0000000..da92e37
--- /dev/null
+++ b/omx/gstomxavsdec.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ *   Author: Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxavsdec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_avs_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_avs_dec_debug_category
+
+/* prototypes */
+static gboolean gst_omx_avs_dec_is_format_change (GstOMXVideoDec * dec,
+    GstOMXPort * port, GstVideoCodecState * state);
+static gboolean gst_omx_avs_dec_set_format (GstOMXVideoDec * dec,
+    GstOMXPort * port, GstVideoCodecState * state);
+
+enum
+{
+  PROP_0
+};
+
+/* class initialization */
+
+#define DEBUG_INIT \
+  GST_DEBUG_CATEGORY_INIT (gst_omx_avs_dec_debug_category, "omxavsdec", 0, \
+      "debug category for gst-omx video decoder base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXAVSDec, gst_omx_avs_dec,
+    GST_TYPE_OMX_VIDEO_DEC, DEBUG_INIT);
+
+static void
+gst_omx_avs_dec_class_init (GstOMXAVSDecClass * klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstOMXVideoDecClass *videodec_class = GST_OMX_VIDEO_DEC_CLASS (klass);
+
+  videodec_class->is_format_change =
+      GST_DEBUG_FUNCPTR (gst_omx_avs_dec_is_format_change);
+  videodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_avs_dec_set_format);
+
+  videodec_class->cdata.default_sink_template_caps = "video/x-cavs";
+
+  gst_element_class_set_static_metadata (element_class,
+      "OpenMAX AVS Video Decoder",
+      "Codec/Decoder/Video",
+      "Decode AVS video streams",
+      "Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>");
+
+  gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.avs");
+}
+
+static void
+gst_omx_avs_dec_init (GstOMXAVSDec * self)
+{
+}
+
+static gboolean
+gst_omx_avs_dec_is_format_change (GstOMXVideoDec * dec,
+    GstOMXPort * port, GstVideoCodecState * state)
+{
+  return FALSE;
+}
+
+static gboolean
+gst_omx_avs_dec_set_format (GstOMXVideoDec * dec, GstOMXPort * port,
+    GstVideoCodecState * state)
+{
+  gboolean ret;
+  OMX_PARAM_PORTDEFINITIONTYPE port_def;
+
+  gst_omx_port_get_port_definition (port, &port_def);
+  port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingAVS;
+  ret = gst_omx_port_update_port_definition (port, &port_def) == OMX_ErrorNone;
+
+  return ret;
+}
diff --git a/omx/gstomxavsdec.h b/omx/gstomxavsdec.h
new file mode 100644
index 0000000..29172a2
--- /dev/null
+++ b/omx/gstomxavsdec.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ *   Author: Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifndef __GST_OMX_AVS_DEC_H__
+#define __GST_OMX_AVS_DEC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_AVS_DEC \
+  (gst_omx_avs_dec_get_type())
+#define GST_OMX_AVS_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_AVS_DEC,GstOMXAVSDec))
+#define GST_OMX_AVS_DEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_AVS_DEC,GstOMXAVSDecClass))
+#define GST_OMX_AVS_DEC_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_AVS_DEC,GstOMXAVSDecClass))
+#define GST_IS_OMX_AVS_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_AVS_DEC))
+#define GST_IS_OMX_AVS_DEC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_AVS_DEC))
+
+typedef struct _GstOMXAVSDec GstOMXAVSDec;
+typedef struct _GstOMXAVSDecClass GstOMXAVSDecClass;
+
+struct _GstOMXAVSDec
+{
+  GstOMXVideoDec parent;
+};
+
+struct _GstOMXAVSDecClass
+{
+  GstOMXVideoDecClass parent_class;
+};
+
+GType gst_omx_avs_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_AVS_DEC_H__ */
diff --git a/omx/gstomxbufferpool.c b/omx/gstomxbufferpool.c
index b885685..2dc07fc 100644
--- a/omx/gstomxbufferpool.c
+++ b/omx/gstomxbufferpool.c
@@ -360,6 +360,7 @@ gst_omx_buffer_pool_alloc_buffer (GstBufferPool * bpool,
       case GST_VIDEO_FORMAT_YVYU:
       case GST_VIDEO_FORMAT_GRAY8:
         break;
+      case GST_VIDEO_FORMAT_YV12:
       case GST_VIDEO_FORMAT_I420:
         stride[1] = nstride / 2;
         offset[1] = offset[0] + stride[0] * nslice;
@@ -370,6 +371,7 @@ gst_omx_buffer_pool_alloc_buffer (GstBufferPool * bpool,
       case GST_VIDEO_FORMAT_NV12_10LE32:
       case GST_VIDEO_FORMAT_NV16:
       case GST_VIDEO_FORMAT_NV16_10LE32:
+      case GST_VIDEO_FORMAT_NV21:
         stride[1] = nstride;
         offset[1] = offset[0] + stride[0] * nslice;
         break;
diff --git a/omx/gstomxdivx4dec.c b/omx/gstomxdivx4dec.c
new file mode 100644
index 0000000..52dd5ad
--- /dev/null
+++ b/omx/gstomxdivx4dec.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ *   Author: Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxdivx4dec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_divx4_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_divx4_dec_debug_category
+
+/* prototypes */
+static gboolean gst_omx_divx4_dec_is_format_change (GstOMXVideoDec * dec,
+    GstOMXPort * port, GstVideoCodecState * state);
+static gboolean gst_omx_divx4_dec_set_format (GstOMXVideoDec * dec,
+    GstOMXPort * port, GstVideoCodecState * state);
+
+enum
+{
+  PROP_0
+};
+
+/* class initialization */
+
+#define DEBUG_INIT \
+  GST_DEBUG_CATEGORY_INIT (gst_omx_divx4_dec_debug_category, "omxdivx4dec", 0, \
+      "debug category for gst-omx video decoder base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXDIVX4Dec, gst_omx_divx4_dec,
+    GST_TYPE_OMX_VIDEO_DEC, DEBUG_INIT);
+
+static void
+gst_omx_divx4_dec_class_init (GstOMXDIVX4DecClass * klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstOMXVideoDecClass *videodec_class = GST_OMX_VIDEO_DEC_CLASS (klass);
+
+  videodec_class->is_format_change =
+      GST_DEBUG_FUNCPTR (gst_omx_divx4_dec_is_format_change);
+  videodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_divx4_dec_set_format);
+
+  videodec_class->cdata.default_sink_template_caps = "video/x-divx, "
+	  "divxversion=(int)4, "
+	  "width=(int) [1,MAX], " "height=(int) [1,MAX]";
+
+  gst_element_class_set_static_metadata (element_class,
+      "OpenMAX DIVX4 Video Decoder",
+      "Codec/Decoder/Video",
+      "Decode DIVX4 video streams",
+      "Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>");
+
+  gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.divx4");
+}
+
+static void
+gst_omx_divx4_dec_init (GstOMXDIVX4Dec * self)
+{
+}
+
+static gboolean
+gst_omx_divx4_dec_is_format_change (GstOMXVideoDec * dec,
+    GstOMXPort * port, GstVideoCodecState * state)
+{
+  return FALSE;
+}
+
+static gboolean
+gst_omx_divx4_dec_set_format (GstOMXVideoDec * dec, GstOMXPort * port,
+    GstVideoCodecState * state)
+{
+  gboolean ret;
+  OMX_PARAM_PORTDEFINITIONTYPE port_def;
+
+  gst_omx_port_get_port_definition (port, &port_def);
+  port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingDIVX4;
+  ret = gst_omx_port_update_port_definition (port, &port_def) == OMX_ErrorNone;
+
+  return ret;
+}
diff --git a/omx/gstomxdivx4dec.h b/omx/gstomxdivx4dec.h
new file mode 100644
index 0000000..d9b0927
--- /dev/null
+++ b/omx/gstomxdivx4dec.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ *   Author: Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifndef __GST_OMX_DIVX4_DEC_H__
+#define __GST_OMX_DIVX4_DEC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_DIVX4_DEC \
+  (gst_omx_divx4_dec_get_type())
+#define GST_OMX_DIVX4_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_DIVX4_DEC,GstOMXDIVX4Dec))
+#define GST_OMX_DIVX4_DEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_DIVX4_DEC,GstOMXDIVX4DecClass))
+#define GST_OMX_DIVX4_DEC_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_DIVX4_DEC,GstOMXDIVX4DecClass))
+#define GST_IS_OMX_DIVX4_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_DIVX4_DEC))
+#define GST_IS_OMX_DIVX4_DEC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_DIVX4_DEC))
+
+typedef struct _GstOMXDIVX4Dec GstOMXDIVX4Dec;
+typedef struct _GstOMXDIVX4DecClass GstOMXDIVX4DecClass;
+
+struct _GstOMXDIVX4Dec
+{
+  GstOMXVideoDec parent;
+};
+
+struct _GstOMXDIVX4DecClass
+{
+  GstOMXVideoDecClass parent_class;
+};
+
+GType gst_omx_divx4_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_DIVX4_DEC_H__ */
diff --git a/omx/gstomxdivxdec.c b/omx/gstomxdivxdec.c
new file mode 100644
index 0000000..38d06d2
--- /dev/null
+++ b/omx/gstomxdivxdec.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ *   Author: Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "OMX_Video.h"
+#include <gst/gst.h>
+#include <stdio.h>
+
+#include "gstomxdivxdec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_divx_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_divx_dec_debug_category
+
+/* prototypes */
+static gboolean gst_omx_divx_dec_is_format_change (GstOMXVideoDec * dec,
+    GstOMXPort * port, GstVideoCodecState * state);
+static gboolean gst_omx_divx_dec_set_format (GstOMXVideoDec * dec,
+    GstOMXPort * port, GstVideoCodecState * state);
+
+enum
+{
+  PROP_0
+};
+
+/* class initialization */
+
+#define DEBUG_INIT \
+  GST_DEBUG_CATEGORY_INIT (gst_omx_divx_dec_debug_category, "omxdivxdec", 0, \
+      "debug category for gst-omx video decoder base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXDIVXDec, gst_omx_divx_dec,
+    GST_TYPE_OMX_VIDEO_DEC, DEBUG_INIT);
+
+static void
+gst_omx_divx_dec_class_init (GstOMXDIVXDecClass * klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstOMXVideoDecClass *videodec_class = GST_OMX_VIDEO_DEC_CLASS (klass);
+  videodec_class->is_format_change =
+      GST_DEBUG_FUNCPTR (gst_omx_divx_dec_is_format_change);
+  videodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_divx_dec_set_format);
+
+  videodec_class->cdata.default_sink_template_caps = "video/x-divx, "
+	  "divxversion=(int)5, "
+      "parsed=(boolean) true, " "width=(int) [1,MAX], " "height=(int) [1,MAX]";
+
+  gst_element_class_set_static_metadata (element_class,
+      "OpenMAX divx Video Decoder",
+      "Codec/Decoder/Video",
+      "Decode divx video streams",
+      "Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>");
+
+  gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.divx");
+}
+
+static void
+gst_omx_divx_dec_init (GstOMXDIVXDec * self)
+{
+}
+
+static gboolean
+gst_omx_divx_dec_is_format_change (GstOMXVideoDec * dec,
+    GstOMXPort * port, GstVideoCodecState * state)
+{
+  return FALSE;
+}
+
+static gboolean
+gst_omx_divx_dec_set_format (GstOMXVideoDec * dec, GstOMXPort * port,
+    GstVideoCodecState * state)
+{
+  gboolean ret;
+  OMX_PARAM_PORTDEFINITIONTYPE port_def;
+  gst_omx_port_get_port_definition (port, &port_def);
+  port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingDIVX;
+  ret = gst_omx_port_update_port_definition (port, &port_def) == OMX_ErrorNone;
+
+  return ret;
+}
diff --git a/omx/gstomxdivxdec.h b/omx/gstomxdivxdec.h
new file mode 100644
index 0000000..c4bc66f
--- /dev/null
+++ b/omx/gstomxdivxdec.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ *   Author: Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifndef __GST_OMX_DIVX_DEC_H__
+#define __GST_OMX_DIVX_DEC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_DIVX_DEC \
+  (gst_omx_divx_dec_get_type())
+#define GST_OMX_DIVX_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_DIVX_DEC,GstOMXDIVXDec))
+#define GST_OMX_DIVX_DEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_DIVX_DEC,GstOMXDIVXDecClass))
+#define GST_OMX_DIVX_DEC_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_DIVX_DEC,GstOMXDIVXDecClass))
+#define GST_IS_OMX_DIVX_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_DIVX_DEC))
+#define GST_IS_OMX_DIVX_DEC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_DIVX_DEC))
+
+typedef struct _GstOMXDIVXDec GstOMXDIVXDec;
+typedef struct _GstOMXDIVXDecClass GstOMXDIVXDecClass;
+
+struct _GstOMXDIVXDec
+{
+  GstOMXVideoDec parent;
+};
+
+struct _GstOMXDIVXDecClass
+{
+  GstOMXVideoDecClass parent_class;
+};
+
+GType gst_omx_divx_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_DIVX_DEC_H__ */
diff --git a/omx/gstomxh264dec.c b/omx/gstomxh264dec.c
index 32b5757..6f98de2 100644
--- a/omx/gstomxh264dec.c
+++ b/omx/gstomxh264dec.c
@@ -53,7 +53,7 @@ G_DEFINE_TYPE_WITH_CODE (GstOMXH264Dec, gst_omx_h264_dec,
 #define MAKE_CAPS(alignment) \
   "video/x-h264, " \
       "alignment=(string) " alignment ", " \
-      "stream-format=(string) byte-stream, " \
+      "stream-format=(string) { avc, avc3, byte-stream }, " \
       "width=(int) [1,MAX], height=(int) [1,MAX]"
 
 /* The Zynq supports decoding subframes, though we want "au" to be the
diff --git a/omx/gstomxh264enc.c b/omx/gstomxh264enc.c
index 51d84a8..1a67b56 100644
--- a/omx/gstomxh264enc.c
+++ b/omx/gstomxh264enc.c
@@ -26,6 +26,7 @@
 
 #include "gstomxh264enc.h"
 #include "gstomxh264utils.h"
+#include "AWOMX_VideoIndexExtension.h"
 
 #ifdef USE_OMX_TARGET_RPI
 #include <OMX_Broadcom.h>
@@ -723,6 +724,14 @@ gst_omx_h264_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
   gst_omx_port_set_subframe (GST_OMX_VIDEO_ENC (self)->enc_out_port,
       enable_subframe);
 
+  //AW CODE START
+  //Set avc enc csd mode to 1. In this mode, csd data will set with firstframe.
+  //Default mode is 0, while csd data will produce separately.
+  int mode = 1;
+  err = gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+      AWOMX_IndexVendorSetVencCsdMode, &mode);
+  //AW CODE END
+
   if (!update_param_avc (self, profile, level))
     return FALSE;
 
diff --git a/omx/gstomxh265dec.c b/omx/gstomxh265dec.c
index f8abf41..8e49989 100644
--- a/omx/gstomxh265dec.c
+++ b/omx/gstomxh265dec.c
@@ -54,7 +54,7 @@ G_DEFINE_TYPE_WITH_CODE (GstOMXH265Dec, gst_omx_h265_dec,
 #define MAKE_CAPS(alignment) \
    "video/x-h265, " \
       "alignment=(string) " alignment ", " \
-      "stream-format=(string) byte-stream, " \
+      "stream-format=(string) { hvc1, hev1, byte-stream }, " \
       "width=(int) [1,MAX], height=(int) [1,MAX]"
 
 /* The Zynq MPSoC supports decoding subframes though we want "au" to be the
diff --git a/omx/gstomxmjpegenc.c b/omx/gstomxmjpegenc.c
new file mode 100644
index 0000000..ebab606
--- /dev/null
+++ b/omx/gstomxmjpegenc.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ *   Author: Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxmjpegenc.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_mjpeg_enc_debug_category);
+#define GST_CAT_DEFAULT gst_omx_mjpeg_enc_debug_category
+
+/* prototypes */
+static gboolean gst_omx_mjpeg_enc_set_format (GstOMXVideoEnc * enc,
+    GstOMXPort * port, GstVideoCodecState * state);
+static GstCaps *gst_omx_mjpeg_enc_get_caps (GstOMXVideoEnc * enc,
+    GstOMXPort * port, GstVideoCodecState * state);
+
+enum
+{
+  PROP_0
+};
+
+/* class initialization */
+
+#define DEBUG_INIT \
+  GST_DEBUG_CATEGORY_INIT (gst_omx_mjpeg_enc_debug_category, "omxmjpegenc", 0, \
+      "debug category for gst-omx video encoder base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXMJPEGEnc, gst_omx_mjpeg_enc,
+    GST_TYPE_OMX_VIDEO_ENC, DEBUG_INIT);
+
+static void
+gst_omx_mjpeg_enc_class_init (GstOMXMJPEGEncClass * klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstOMXVideoEncClass *videoenc_class = GST_OMX_VIDEO_ENC_CLASS (klass);
+  videoenc_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_mjpeg_enc_set_format);
+  videoenc_class->get_caps = GST_DEBUG_FUNCPTR (gst_omx_mjpeg_enc_get_caps);
+
+  videoenc_class->cdata.default_src_template_caps = "image/jpeg";
+
+  gst_element_class_set_static_metadata (element_class,
+      "OpenMAX Mjpeg Video Encoder",
+      "Codec/Encoder/Video",
+      "Encode Mjpeg video streams",
+      "Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>");
+
+  gst_omx_set_default_role (&videoenc_class->cdata, "video_encoder.mjpeg");
+}
+
+static void
+gst_omx_mjpeg_enc_init (GstOMXMJPEGEnc * self)
+{
+}
+
+static gboolean
+gst_omx_mjpeg_enc_set_format (GstOMXVideoEnc * enc, GstOMXPort * port,
+    GstVideoCodecState * state)
+{
+  GstOMXMJPEGEnc *self = GST_OMX_MJPEG_ENC (enc);
+  GstCaps *peercaps;
+  OMX_PARAM_PORTDEFINITIONTYPE port_def;
+  OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+  OMX_ERRORTYPE err;
+  guint profile_id, level_id;
+
+  gst_omx_port_get_port_definition (GST_OMX_VIDEO_ENC (self)->enc_out_port,
+      &port_def);
+  port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingMJPEG;
+  err =
+      gst_omx_port_update_port_definition (GST_OMX_VIDEO_ENC
+      (self)->enc_out_port, &port_def);
+  if (err != OMX_ErrorNone)
+    return FALSE;
+
+  GST_OMX_INIT_STRUCT (&param);
+  param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+//   err =
+//       gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+//       OMX_IndexParamVideoProfileLevelCurrent, &param);
+//   if (err != OMX_ErrorNone) {
+//     GST_WARNING_OBJECT (self,
+//         "Getting profile/level not supported by component");
+//     return TRUE;
+//   }
+
+  peercaps = gst_pad_peer_query_caps (GST_VIDEO_ENCODER_SRC_PAD (enc),
+      gst_pad_get_pad_template_caps (GST_VIDEO_ENCODER_SRC_PAD (enc)));
+  if (peercaps) {
+    GstStructure *s;
+
+    if (gst_caps_is_empty (peercaps)) {
+      gst_caps_unref (peercaps);
+      GST_ERROR_OBJECT (self, "Empty caps");
+      return FALSE;
+    }
+
+    s = gst_caps_get_structure (peercaps, 0);
+    gst_caps_unref (peercaps);
+  }
+
+//   err =
+//       gst_omx_component_set_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+//       OMX_IndexParamVideoProfileLevelCurrent, &param);
+//   if (err == OMX_ErrorUnsupportedIndex) {
+//     GST_WARNING_OBJECT (self,
+//         "Setting profile/level not supported by component");
+//   } else if (err != OMX_ErrorNone) {
+//     GST_ERROR_OBJECT (self,
+//         "Error setting profile %u and level %u: %s (0x%08x)",
+//         (guint) param.eProfile, (guint) param.eLevel,
+//         gst_omx_error_to_string (err), err);
+//     return FALSE;
+//   }
+
+  return TRUE;
+
+unsupported_profile:
+  GST_ERROR_OBJECT (self, "Unsupported profile %u", profile_id);
+  gst_caps_unref (peercaps);
+  return FALSE;
+
+unsupported_level:
+  GST_ERROR_OBJECT (self, "Unsupported level %u", level_id);
+  gst_caps_unref (peercaps);
+  return FALSE;
+}
+
+static GstCaps *
+gst_omx_mjpeg_enc_get_caps (GstOMXVideoEnc * enc, GstOMXPort * port,
+    GstVideoCodecState * state)
+{
+  GstOMXMJPEGEnc *self = GST_OMX_MJPEG_ENC (enc);
+  GstCaps *caps;
+  OMX_ERRORTYPE err;
+  OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+  guint profile, level;
+
+  caps = gst_caps_new_empty_simple ("image/jpeg");
+
+  GST_OMX_INIT_STRUCT (&param);
+  param.nPortIndex = GST_OMX_VIDEO_ENC (self)->enc_out_port->index;
+
+  err =
+      gst_omx_component_get_parameter (GST_OMX_VIDEO_ENC (self)->enc,
+      OMX_IndexParamVideoProfileLevelCurrent, &param);
+  if (err != OMX_ErrorNone && err != OMX_ErrorUnsupportedIndex) {
+    gst_caps_unref (caps);
+    return NULL;
+  }
+
+  return caps;
+}
diff --git a/omx/gstomxmjpegenc.h b/omx/gstomxmjpegenc.h
new file mode 100644
index 0000000..52d06eb
--- /dev/null
+++ b/omx/gstomxmjpegenc.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ *   Author: Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifndef __GST_OMX_MJPEG_ENC_H__
+#define __GST_OMX_MJPEG_ENC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideoenc.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_MJPEG_ENC \
+  (gst_omx_mjpeg_enc_get_type())
+#define GST_OMX_MJPEG_ENC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_MJPEG_ENC,GstOMXMJPEGEnc))
+#define GST_OMX_MJPEG_ENC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_MJPEG_ENC,GstOMXMJPEGEncClass))
+#define GST_OMX_MJPEG_ENC_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_MJPEG_ENC,GstOMXMJPEGEncClass))
+#define GST_IS_OMX_MJPEG_ENC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_MJPEG_ENC))
+#define GST_IS_OMX_MJPEG_ENC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_MJPEG_ENC))
+
+typedef struct _GstOMXMJPEGEnc GstOMXMJPEGEnc;
+typedef struct _GstOMXMJPEGEncClass GstOMXMJPEGEncClass;
+
+struct _GstOMXMJPEGEnc
+{
+  GstOMXVideoEnc parent;
+};
+
+struct _GstOMXMJPEGEncClass
+{
+  GstOMXVideoEncClass parent_class;
+};
+
+GType gst_omx_mjpeg_enc_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_MJPEG_ENC_H__ */
diff --git a/omx/gstomxmpeg1dec.c b/omx/gstomxmpeg1dec.c
new file mode 100644
index 0000000..81d6ff6
--- /dev/null
+++ b/omx/gstomxmpeg1dec.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ *   Author: Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include "gstomxmpeg1dec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_mpeg1_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_mpeg1_dec_debug_category
+
+/* prototypes */
+static gboolean gst_omx_mpeg1_dec_is_format_change (GstOMXVideoDec * dec,
+    GstOMXPort * port, GstVideoCodecState * state);
+static gboolean gst_omx_mpeg1_dec_set_format (GstOMXVideoDec * dec,
+    GstOMXPort * port, GstVideoCodecState * state);
+
+enum
+{
+  PROP_0
+};
+
+/* class initialization */
+
+#define DEBUG_INIT \
+  GST_DEBUG_CATEGORY_INIT (gst_omx_mpeg1_dec_debug_category, "omxmpeg1dec", 0, \
+      "debug category for gst-omx video decoder base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXMPEG1Dec, gst_omx_mpeg1_dec,
+    GST_TYPE_OMX_VIDEO_DEC, DEBUG_INIT);
+
+static void
+gst_omx_mpeg1_dec_class_init (GstOMXMPEG1DecClass * klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstOMXVideoDecClass *videodec_class = GST_OMX_VIDEO_DEC_CLASS (klass);
+
+  videodec_class->is_format_change =
+      GST_DEBUG_FUNCPTR (gst_omx_mpeg1_dec_is_format_change);
+  videodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_mpeg1_dec_set_format);
+
+  videodec_class->cdata.default_sink_template_caps = "video/mpeg, "
+	  "mpegversion=(int)1, "
+	  "systemstream=(boolean) false, "
+	  "width=(int) [1,MAX], " "height=(int) [1,MAX]";
+
+  gst_element_class_set_static_metadata (element_class,
+      "OpenMAX MPEG1 Video Decoder",
+      "Codec/Decoder/Video",
+      "Decode MPEG1 video streams",
+      "Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>");
+
+  gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.mpeg1");
+}
+
+static void
+gst_omx_mpeg1_dec_init (GstOMXMPEG1Dec * self)
+{
+}
+
+static gboolean
+gst_omx_mpeg1_dec_is_format_change (GstOMXVideoDec * dec,
+    GstOMXPort * port, GstVideoCodecState * state)
+{
+  return FALSE;
+}
+
+static gboolean
+gst_omx_mpeg1_dec_set_format (GstOMXVideoDec * dec, GstOMXPort * port,
+    GstVideoCodecState * state)
+{
+  gboolean ret;
+  OMX_PARAM_PORTDEFINITIONTYPE port_def;
+
+  gst_omx_port_get_port_definition (port, &port_def);
+  port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG1;
+  ret = gst_omx_port_update_port_definition (port, &port_def) == OMX_ErrorNone;
+
+  return ret;
+}
diff --git a/omx/gstomxmpeg1dec.h b/omx/gstomxmpeg1dec.h
new file mode 100644
index 0000000..9bd1d4c
--- /dev/null
+++ b/omx/gstomxmpeg1dec.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ *   Author: Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifndef __GST_OMX_MPEG1_DEC_H__
+#define __GST_OMX_MPEG1_DEC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideodec.h"
+#include "gstomx.h"
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_MPEG1_DEC \
+  (gst_omx_mpeg1_dec_get_type())
+#define GST_OMX_MPEG1_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_MPEG1_DEC,GstOMXMPEG1Dec))
+#define GST_OMX_MPEG1_DEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_MPEG1_DEC,GstOMXMPEG1DecClass))
+#define GST_OMX_MPEG1_DEC_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_MPEG1_DEC,GstOMXMPEG1DecClass))
+#define GST_IS_OMX_MPEG1_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_MPEG1_DEC))
+#define GST_IS_OMX_MPEG1_DEC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_MPEG1_DEC))
+
+typedef struct _GstOMXMPEG1Dec GstOMXMPEG1Dec;
+typedef struct _GstOMXMPEG1DecClass GstOMXMPEG1DecClass;
+
+struct _GstOMXMPEG1Dec
+{
+  GstOMXVideoDec parent;
+};
+
+struct _GstOMXMPEG1DecClass
+{
+  GstOMXVideoDecClass parent_class;
+};
+
+GType gst_omx_mpeg1_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_MPEG1_DEC_H__ */
diff --git a/omx/gstomxvideo.c b/omx/gstomxvideo.c
index e08ff4c..816a0b2 100644
--- a/omx/gstomxvideo.c
+++ b/omx/gstomxvideo.c
@@ -28,6 +28,9 @@
 
 #include "gstomxvideo.h"
 
+#include <gst/allocators/gstdmabuf.h>
+#include <gst/video/video.h>
+
 #include <math.h>
 
 GST_DEBUG_CATEGORY (gst_omx_video_debug_category);
@@ -94,6 +97,12 @@ gst_omx_video_get_format_from_omx (OMX_COLOR_FORMATTYPE omx_colorformat)
       break;
 #pragma GCC diagnostic pop
 #endif
+    case OMX_COLOR_FormatYVU420SemiPlanar:
+      format = GST_VIDEO_FORMAT_NV21;
+      break;
+    case OMX_COLOR_FormatYVU420Planar:
+      format = GST_VIDEO_FORMAT_YV12;
+      break;
     default:
       format = GST_VIDEO_FORMAT_UNKNOWN;
       break;
@@ -160,7 +169,10 @@ gst_omx_video_get_supported_colorformats (GstOMXPort * port,
 GstCaps *
 gst_omx_video_get_caps_for_map (GList * map)
 {
-  GstCaps *caps = gst_caps_new_empty ();
+  const gchar *capsString = GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_DMABUF,
+    GST_OMX_VIDEO_DEC_SUPPORTED_FORMATS);
+
+  GstCaps *caps = gst_caps_from_string(capsString);
   GList *l;
 
   for (l = map; l; l = l->next) {
@@ -171,6 +183,7 @@ gst_omx_video_get_caps_for_map (GList * map)
             "format", G_TYPE_STRING,
             gst_video_format_to_string (entry->format), NULL));
   }
+
   return caps;
 }
 
diff --git a/omx/gstomxvideo.h b/omx/gstomxvideo.h
index 8664345..43907a8 100644
--- a/omx/gstomxvideo.h
+++ b/omx/gstomxvideo.h
@@ -35,11 +35,10 @@
 G_BEGIN_DECLS
 
 /* Keep synced with gst_omx_video_get_format_from_omx(). Sort by decreasing quality */
-#define GST_OMX_VIDEO_DEC_SUPPORTED_FORMATS "{ NV16_10LE32, NV12_10LE32, " \
-  "NV16, YUY2, YVYU, UYVY, NV12, I420, RGB16, BGR16, ABGR, ARGB, GRAY8 }"
+#define GST_OMX_VIDEO_DEC_SUPPORTED_FORMATS "{ YV12, NV21 }"
 
 #define GST_OMX_VIDEO_ENC_SUPPORTED_FORMATS "{ NV16_10LE32, NV12_10LE32, " \
-  "NV16, NV12, I420, GRAY8 }"
+  "NV16, NV12, I420, GRAY8, YV12, NV21 }"
 
 typedef struct
 {
diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c
index 917ce8a..9618caa 100644
--- a/omx/gstomxvideodec.c
+++ b/omx/gstomxvideodec.c
@@ -26,6 +26,12 @@
 
 #include <gst/gst.h>
 #include <gst/allocators/gstdmabuf.h>
+#include <gst/gstbuffer.h>
+#include <gst/gstcaps.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include "AWOMX_VideoIndexExtension.h"
 
 #if defined (USE_OMX_TARGET_RPI) && defined(__GNUC__)
 #ifndef __VCCOREVER__
@@ -46,6 +52,8 @@
 #pragma GCC diagnostic pop
 #endif
 
+#define GST_OMX_VIDEO_DEC_SCALE_DEFAULT 0
+
 #include <string.h>
 
 #include "gstomxbufferpool.h"
@@ -55,6 +63,9 @@
 GST_DEBUG_CATEGORY_STATIC (gst_omx_video_dec_debug_category);
 #define GST_CAT_DEFAULT gst_omx_video_dec_debug_category
 
+static GstVideoFormat GST_OMX_VIDEO_DEC_ARM_AFBC = FALSE;
+static gboolean gst_omx_video_dec_debug_enabled = FALSE;
+
 /* prototypes */
 static void gst_omx_video_dec_finalize (GObject * object);
 
@@ -88,6 +99,9 @@ enum
 {
   PROP_0,
   PROP_INTERNAL_ENTROPY_BUFFERS,
+  PROP_SCALE,
+  PROP_DISABLE_DMA_FEATURE,
+  PROP_ARM_AFBC,
 };
 
 #define GST_OMX_VIDEO_DEC_INTERNAL_ENTROPY_BUFFERS_DEFAULT (5)
@@ -106,9 +120,7 @@ static void
 gst_omx_video_dec_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
 {
-#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
   GstOMXVideoDec *self = GST_OMX_VIDEO_DEC (object);
-#endif
 
   switch (prop_id) {
 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
@@ -116,6 +128,15 @@ gst_omx_video_dec_set_property (GObject * object, guint prop_id,
       self->internal_entropy_buffers = g_value_get_uint (value);
       break;
 #endif
+    case PROP_SCALE:
+      self->scale = g_value_get_uint(value);
+      break;
+    case PROP_DISABLE_DMA_FEATURE:
+      self->disable_dma_feature = g_value_get_boolean(value);
+      break;
+    case PROP_ARM_AFBC:
+      self->arm_afbc = g_value_get_boolean(value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -126,9 +147,7 @@ static void
 gst_omx_video_dec_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec)
 {
-#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
   GstOMXVideoDec *self = GST_OMX_VIDEO_DEC (object);
-#endif
 
   switch (prop_id) {
 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
@@ -136,12 +155,106 @@ gst_omx_video_dec_get_property (GObject * object, guint prop_id,
       g_value_set_uint (value, self->internal_entropy_buffers);
       break;
 #endif
+    case PROP_SCALE:
+      g_value_set_uint(value, self->scale);
+      break;
+    case PROP_DISABLE_DMA_FEATURE:
+      g_value_set_boolean(value, self->disable_dma_feature);
+      break;
+    case PROP_ARM_AFBC:
+      g_value_set_boolean (value, self->arm_afbc);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
 }
 
+static void add_meta_to_output(GstBuffer *buf, OmxPrivateBuffer *private)
+{
+  GstVideoCropMeta *meta = NULL;
+  meta = gst_buffer_add_video_crop_meta(buf);
+  meta->x = 0;
+  meta->y = 0;
+  meta->width = private->nWidth;
+  meta->height = private->nHeight;
+
+  if (gst_omx_video_dec_debug_enabled) {
+    GstVideoMeta *vmeta = gst_buffer_get_video_meta(buf);
+    if(vmeta) {
+        GST_INFO_OBJECT(NULL, "video meta info: w=%d h=%d, format=%d", vmeta->width, vmeta->height, vmeta->format);
+      for(gint i = 0 ; i < vmeta->n_planes; i++) {
+        GST_INFO_OBJECT(NULL, "plane %d: stride=%d, offset=%d", i, vmeta->stride[i], vmeta->offset[i]);
+      }
+    }
+
+    if (!gst_is_dmabuf_memory (gst_buffer_peek_memory (buf, 0))) {
+      GST_INFO_OBJECT (NULL, "output frame not dmabuf");
+    } else {
+      gint fd = gst_dmabuf_memory_get_fd(gst_buffer_peek_memory (buf, 0));
+      GST_INFO_OBJECT(NULL, "getDmaBuf fd %d", fd);
+      gint offset = 0, max = 0;
+      gint size = gst_memory_get_sizes(gst_buffer_peek_memory (buf, 0), &offset, &max);
+      GST_INFO_OBJECT(NULL, "dma buffer size = %d", size);
+    }
+    GST_INFO_OBJECT(NULL, "private %p crop info [left %d top %d width %d height %d]",
+                          private, private->nLeft, private->nTop, private->nWidth, private->nHeight);
+  }
+}
+
+// static GstBuffer * wrapper_omx_buffer(GstBuffer *buffer)
+// {
+//     GstMemory *mem;
+
+//     mem = gst_buffer_get_memory(buffer, 0);
+
+//     if (gst_is_dmabuf_memory(mem)) {
+//       int fd = gst_dmabuf_memory_get_fd(mem);
+//       GST_ERROR_OBJECT(NULL, "fd %d", fd);
+//     }
+
+
+//     return NULL;
+    // OmxPrivateBuffer *sOmxOutPrivateBuffer;
+    // GstMapInfo map;
+    // guint8 *data = NULL;
+    // GstBuffer *result = NULL;
+    // GstVideoCropMeta *meta = NULL;
+    // GstCustomMeta *aw_meta = NULL;
+    // GstStructure *s;
+    // int size;
+
+    // if (gst_buffer_map(buffer, &map, GST_MAP_READ)) {
+    //     sOmxOutPrivateBuffer = (OmxPrivateBuffer *) map.data;
+    //     data = (guint8 *) sOmxOutPrivateBuffer->pAddrVirY;
+    //     size = sOmxOutPrivateBuffer->nBufferSize;
+    //     gst_buffer_unmap(buffer, &map);
+
+    //     result =  gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_READONLY, data, size, 0, size, buffer, free_buffer);
+    //     result->pts = buffer->pts;
+    //     result->dts = buffer->dts;
+    //     result->duration = buffer->duration;
+    //     result->offset = buffer->offset;
+    //     result->offset = buffer->offset_end;
+
+    //     meta = gst_buffer_add_video_crop_meta(result);
+    //     meta->x = 0;
+    //     meta->y = 0;
+    //     meta->width = sOmxOutPrivateBuffer->nWidth;
+    //     meta->height = sOmxOutPrivateBuffer->nHeight;
+
+    //     aw_meta = gst_buffer_add_custom_meta(result, "GstAwMeta");
+    //     s = gst_custom_meta_get_structure(aw_meta);
+    //     gst_structure_set(s,
+    //                       "aw_buffer_fd", G_TYPE_INT, sOmxOutPrivateBuffer->nShareBufFd, NULL);
+    //     gst_structure_set(s,
+    //                       "aw_buffer_phy", G_TYPE_UINT64, (guint64)sOmxOutPrivateBuffer->pAddrPhyY, NULL);
+    //     return result;
+    // } else {
+    //     return NULL;
+    // }
+//}
+
 static void
 gst_omx_video_dec_class_init (GstOMXVideoDecClass * klass)
 {
@@ -149,6 +262,12 @@ gst_omx_video_dec_class_init (GstOMXVideoDecClass * klass)
   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
   GstVideoDecoderClass *video_decoder_class = GST_VIDEO_DECODER_CLASS (klass);
 
+  DEBUG_INIT
+
+  if (g_getenv ("GST_OMX_VIDEO_DEC_DEBUG")) {
+    gst_omx_video_dec_debug_enabled = TRUE;
+  }
+
   gobject_class->finalize = gst_omx_video_dec_finalize;
   gobject_class->set_property = gst_omx_video_dec_set_property;
   gobject_class->get_property = gst_omx_video_dec_get_property;
@@ -163,6 +282,26 @@ gst_omx_video_dec_class_init (GstOMXVideoDecClass * klass)
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
           GST_PARAM_MUTABLE_READY));
 #endif
+  g_object_class_install_property (gobject_class, PROP_SCALE,
+      g_param_spec_uint ("scale", "Output Scale",
+          "0 means origin size, 1 means 1/2, 2 means 1/4",
+          0, 2, GST_OMX_VIDEO_DEC_SCALE_DEFAULT,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_DISABLE_DMA_FEATURE,
+      g_param_spec_boolean ("disable-dma-feature", "Feature for downstream",
+          "If set true, the down plugins will no get the DMABuf memory type"
+          "while negotiating",
+          FALSE,
+          (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  if (g_getenv ("GST_AW_OMX_DEFAULT_ARM_AFBC"))
+    GST_OMX_VIDEO_DEC_ARM_AFBC = TRUE;
+
+  g_object_class_install_property (gobject_class, PROP_ARM_AFBC,
+      g_param_spec_boolean ("afbc", "ARM AFBC",
+          "Support to use ARM AFBC compressed format", GST_OMX_VIDEO_DEC_ARM_AFBC,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   element_class->change_state =
       GST_DEBUG_FUNCPTR (gst_omx_video_dec_change_state);
@@ -194,13 +333,21 @@ gst_omx_video_dec_class_init (GstOMXVideoDecClass * klass)
       GST_OMX_VIDEO_DEC_SUPPORTED_FORMATS)
       ", interlace-mode = (string) alternate ; "
 #endif
+      GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_DMABUF, \
+      GST_OMX_VIDEO_DEC_SUPPORTED_FORMATS) ";" \
+      GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_DMABUF, GST_OMX_VIDEO_DEC_SUPPORTED_FORMATS) \
+      ", " AW_OMX_FEATURE_ARM_AFBC " = (int) 1;" \
+      GST_VIDEO_CAPS_MAKE (GST_OMX_VIDEO_DEC_SUPPORTED_FORMATS) ", " AW_OMX_FEATURE_ARM_AFBC " = (int) 1;" \
       GST_VIDEO_CAPS_MAKE (GST_OMX_VIDEO_DEC_SUPPORTED_FORMATS);
 }
 
 static void
 gst_omx_video_dec_init (GstOMXVideoDec * self)
 {
-  self->dmabuf = FALSE;
+  self->dmabuf = TRUE;
+  self->disable_dma_feature = FALSE;
+  self->scale = GST_OMX_VIDEO_DEC_SCALE_DEFAULT;
+  self->arm_afbc = GST_OMX_VIDEO_DEC_ARM_AFBC;
 
 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
   self->internal_entropy_buffers =
@@ -273,6 +420,45 @@ gst_omx_video_dec_open (GstVideoDecoder * decoder)
   if (!self->dec)
     return FALSE;
 
+  if (self->dec && self->scale > 0)
+  {
+    GST_DEBUG_OBJECT(self, "Set Scale %d", self->scale);
+    OMX_CONFIG_SCALEFACTORTYPE config;
+    OMX_ERRORTYPE err;
+
+    GST_OMX_INIT_STRUCT (&config);
+    config.xWidth = self->scale;
+    config.xHeight = self->scale;
+
+    err =
+        gst_omx_component_set_config (self->dec,
+        OMX_IndexConfigCommonScale, &config);
+
+    if (err != OMX_ErrorNone)
+      GST_ERROR_OBJECT (self,
+          "Failed to set scale parameter: %s (0x%08x)",
+          gst_omx_error_to_string (err), err);
+  }
+
+  GST_INFO_OBJECT(self, "AFBC: %d", self->arm_afbc);
+
+  if (self->dec && self->arm_afbc > 0)
+  {
+    GST_INFO_OBJECT(self, "Set AFBC: %d", self->arm_afbc);
+    OMX_ERRORTYPE err;
+    int vdieoExtFlag = 0x00;
+
+    vdieoExtFlag |= AW_VIDEO_AFBC_FLAG;
+    err =
+        gst_omx_component_set_config (self->dec,
+        (OMX_INDEXTYPE)AWOMX_IndexParamVideoSetAfbcHdrFlag, &vdieoExtFlag);
+
+    if (err != OMX_ErrorNone)
+      GST_ERROR_OBJECT (self,
+          "Failed to set video extend parameter: %s (0x%08x)",
+          gst_omx_error_to_string (err), err);
+  }
+
   if (gst_omx_component_get_state (self->dec,
           GST_CLOCK_TIME_NONE) != OMX_StateLoaded)
     return FALSE;
@@ -437,8 +623,12 @@ gst_omx_video_dec_close (GstVideoDecoder * decoder)
 
   self->dec_in_port = NULL;
   self->dec_out_port = NULL;
-  if (self->dec)
-    gst_omx_component_unref (self->dec);
+  if (self->dec) {
+    int refCount = GST_OBJECT_REFCOUNT(self->dec);
+    GST_INFO_OBJECT(self, "dec refCount = %d", refCount);
+    gst_omx_component_unref(self->dec);
+  }
+
   self->dec = NULL;
 
 #if defined (USE_OMX_TARGET_RPI) && defined (HAVE_GST_GL)
@@ -1281,6 +1471,31 @@ gst_omx_video_dec_get_output_interlace_info (GstOMXVideoDec * self)
   return GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
 }
 
+static void
+add_caps_dma_memory_feature (GstCaps * caps)
+{
+  GstCapsFeatures *old, *features;
+
+  features = gst_caps_features_new_empty ();
+  old = gst_caps_get_features (caps, 0);
+
+  if (old) {
+    guint i;
+
+    /* Copy the existing features ignoring memory ones as we are changing
+     * it to GL. */
+    for (i = 0; i < gst_caps_features_get_size (old); i++) {
+      const gchar *f = gst_caps_features_get_nth (old, i);
+
+      if (!g_str_has_prefix (f, "memory:"))
+        gst_caps_features_add (features, f);
+    }
+  }
+
+  gst_caps_features_add (features, GST_CAPS_FEATURE_MEMORY_DMABUF);
+  gst_caps_set_features (caps, 0, features);
+}
+
 #if defined (HAVE_GST_GL)
 static void
 add_caps_gl_memory_feature (GstCaps * caps)
@@ -1308,6 +1523,54 @@ add_caps_gl_memory_feature (GstCaps * caps)
 }
 #endif
 
+//AW CODE START
+/**
+ * Check DMA support through caps negotiation
+ * @param decoder The video decoder element
+ * @return TRUE if DMA caps are accepted
+ */
+static gboolean check_dma_caps_support(GstVideoDecoder *decoder)
+{
+  GstPad *srcpad = gst_element_get_static_pad(GST_ELEMENT(decoder), "src");
+  GstCaps *template_caps;
+  GstCaps *dma_caps;
+  gboolean supported = FALSE;
+
+  if (!srcpad) {
+    GST_WARNING_OBJECT(decoder, "not found src!!!");
+    return FALSE;
+  }
+  // Get pad template caps
+  template_caps = gst_pad_get_pad_template_caps(srcpad);
+  dma_caps = gst_caps_copy(template_caps);
+
+  add_caps_dma_memory_feature(dma_caps);
+  // Check if downstream accepts DMA caps
+  GstCaps *peer_caps = gst_pad_peer_query_caps(srcpad, dma_caps);
+
+  if (peer_caps && !gst_caps_is_empty(peer_caps)) {
+    gchar *peer_caps_str = gst_caps_to_string(peer_caps);
+    GST_INFO_OBJECT(decoder, "Peer caps: %s", peer_caps_str);
+    if(gst_caps_features_contains (gst_caps_get_features (peer_caps, 0), GST_CAPS_FEATURE_MEMORY_DMABUF)) {
+      GST_INFO_OBJECT(decoder, "get DMABuf feature");
+      supported = TRUE;
+    } else {
+      GST_INFO_OBJECT(decoder, " DMA feature not found in caps");
+    }
+    g_free(peer_caps_str);
+  }
+
+  if (peer_caps) {
+    gst_caps_unref(peer_caps);
+  }
+  gst_caps_unref(dma_caps);
+  gst_caps_unref(template_caps);
+  gst_object_unref(srcpad);
+
+  return supported;
+}
+//AW CODE END
+
 static OMX_ERRORTYPE
 gst_omx_video_dec_reconfigure_output_port (GstOMXVideoDec * self)
 {
@@ -1531,7 +1794,6 @@ gst_omx_video_dec_reconfigure_output_port (GstOMXVideoDec * self)
     self->eglimage = FALSE;
   }
 #endif /* defined (HAVE_GST_GL) */
-
   port = self->dec_out_port;
 
   /* Update caps */
@@ -1561,7 +1823,7 @@ gst_omx_video_dec_reconfigure_output_port (GstOMXVideoDec * self)
     interlace_mode = GST_VIDEO_INTERLACE_MODE_ALTERNATE;
   }
 
-  GST_DEBUG_OBJECT (self,
+  GST_INFO_OBJECT (self,
       "Setting output state: format %s (%d), width %u, height %u",
       gst_video_format_to_string (format),
       port_def.format.video.eColorFormat,
@@ -1572,6 +1834,51 @@ gst_omx_video_dec_reconfigure_output_port (GstOMXVideoDec * self)
       format, interlace_mode, port_def.format.video.nFrameWidth,
       frame_height, self->input_state);
 
+  state->caps = gst_video_info_to_caps (&state->info);
+
+  if (!self->disable_dma_feature && check_dma_caps_support(GST_VIDEO_DECODER (self))) {
+    //GstCaps *new_caps = gst_caps_copy(state->caps);
+    add_caps_dma_memory_feature (state->caps);
+    //gst_caps_append(state->caps, new_caps);
+  }
+
+  //AW CODE: check if decoder output with afbc format.
+  gint ext_flag = 0x00;
+  err = gst_omx_component_get_parameter (self->dec,
+      (OMX_INDEXTYPE)AWOMX_IndexParamVideoGetAfbcHdrFlag, &ext_flag);
+
+  if (err != OMX_ErrorNone) {
+    GST_WARNING_OBJECT (self, "Couldn't get extension flag: %s (0x%08x)",
+        gst_omx_error_to_string (err), err);
+  }
+
+  GST_INFO_OBJECT(self, "Get omx extension flag = (0x%08x)", ext_flag);
+
+  if(ext_flag & AW_VIDEO_AFBC_FLAG) {
+    GST_INFO_OBJECT(self, "Found afbc flag from decoder, add afbc caps");
+    gst_caps_set_simple (state->caps,
+        AW_OMX_FEATURE_ARM_AFBC, G_TYPE_INT, TRUE, NULL);
+    //set afbc flag in video info
+    GST_VIDEO_INFO_SET_AFBC (&state->info);
+  } else {
+    GST_VIDEO_INFO_UNSET_AFBC (&state->info);
+  }
+
+  if(ext_flag & AW_VIDEO_10BIT_FLAG) {
+    GST_INFO_OBJECT(self, "Found 10bit buffer flag");
+    GST_VIDEO_INFO_SET_10BIT_BUFFER (&state->info);
+    gst_caps_set_simple (state->caps,"10bit", G_TYPE_INT, TRUE, NULL);
+  } else {
+    GST_VIDEO_INFO_UNSET_10BIT_BUFFER (&state->info);
+  }
+
+  gchar *caps_str = gst_caps_to_string(state->caps);
+  GST_INFO_OBJECT(self, "Setting OMX sink caps = %s", caps_str);
+  g_free(caps_str);
+  //AW CODE end.
+
+  GST_DEBUG_OBJECT(self, "setting caps %" GST_PTR_FORMAT, state->caps);
+
   if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) {
     gst_video_codec_state_unref (state);
     GST_ERROR_OBJECT (self, "Failed to negotiate");
@@ -1580,6 +1887,8 @@ gst_omx_video_dec_reconfigure_output_port (GstOMXVideoDec * self)
     goto done;
   }
 
+  GST_INFO_OBJECT (self, "finish negotiate");
+
   gst_video_codec_state_unref (state);
 
   GST_VIDEO_DECODER_STREAM_UNLOCK (self);
@@ -1954,8 +2263,13 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self)
 
       frame->output_buffer = outbuf;
 
+      OmxPrivateBuffer *sOmxOutPrivateBuffer = (OmxPrivateBuffer*)(buf->omx_buf->pBuffer);
+
+      add_meta_to_output(outbuf, sOmxOutPrivateBuffer);
+
       flow_ret =
           gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
+
       frame = NULL;
       buf = NULL;
     } else {
@@ -2200,7 +2514,7 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
       gst_pad_peer_query_caps (GST_VIDEO_DECODER_SRC_PAD (self), templ_caps);
   gst_caps_unref (templ_caps);
 
-  GST_DEBUG_OBJECT (self, "Allowed downstream caps: %" GST_PTR_FORMAT,
+  GST_INFO_OBJECT (self, "Allowed downstream caps: %" GST_PTR_FORMAT,
       intersection);
 
   negotiation_map =
@@ -2209,7 +2523,7 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
 
   comp_supported_caps = gst_omx_video_get_caps_for_map (negotiation_map);
 
-  GST_DEBUG_OBJECT (self, "Decoder supported caps: %" GST_PTR_FORMAT,
+  GST_INFO_OBJECT (self, "Decoder supported caps: %" GST_PTR_FORMAT,
       comp_supported_caps);
 
   if (!gst_caps_is_empty (comp_supported_caps)) {
@@ -2219,6 +2533,8 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
     gst_caps_unref (intersection);
     intersection = tmp;
   }
+  GST_INFO_OBJECT(self, "intersection %" GST_PTR_FORMAT, intersection);
+
   gst_caps_unref (comp_supported_caps);
 
   if (gst_caps_is_empty (intersection)) {
@@ -2230,10 +2546,15 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
   }
 
   intersection = gst_caps_truncate (intersection);
+  GST_DEBUG_OBJECT(self, "intersection %" GST_PTR_FORMAT, intersection);
+
   intersection = gst_caps_fixate (intersection);
+  GST_DEBUG_OBJECT(self, "intersection %" GST_PTR_FORMAT, intersection);
+
 
   s = gst_caps_get_structure (intersection, 0);
   format_str = gst_structure_get_string (s, "format");
+  GST_INFO_OBJECT(self, "format_str %s", format_str);
   if (!format_str ||
       (format =
           gst_video_format_from_string (format_str)) ==
@@ -2978,8 +3299,8 @@ gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder,
   guint memory_idx = 0;         /* only used in dynamic buffer mode */
   gboolean last_subframe = GST_BUFFER_FLAG_IS_SET (frame->input_buffer,
       GST_VIDEO_BUFFER_FLAG_MARKER);
-  gboolean header =
-      GST_BUFFER_FLAG_IS_SET (frame->input_buffer, GST_BUFFER_FLAG_HEADER);
+  gboolean header = FALSE;
+      //GST_BUFFER_FLAG_IS_SET (frame->input_buffer, GST_BUFFER_FLAG_HEADER);
   gboolean subframe_mode = gst_video_decoder_get_subframe_mode (decoder);
 
   self = GST_OMX_VIDEO_DEC (decoder);
@@ -3010,6 +3331,17 @@ gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder,
   }
 
   timestamp = frame->pts;
+
+  //AW CODE START
+ /* AVI demuxer(gstavidemux) sets non-keyframe PTS to GST_CLOCK_TIME_NONE and set timestamp into dts.
+  * So when PTS is invalid, we just use DTS as alternative to ensure correct frame timing.
+  */
+  if (!GST_CLOCK_TIME_IS_VALID (timestamp)) {
+    timestamp = frame->dts;
+    GST_DEBUG_OBJECT(self, "invalid pts maybe avi? try to use dts: %lu", timestamp);
+  }
+  //AW CODE END
+
   duration = frame->duration;
   port = self->dec_in_port;
 
@@ -3204,7 +3536,7 @@ gst_omx_video_dec_handle_frame (GstVideoDecoder * decoder,
     if (first_ouput_buffer && GST_VIDEO_CODEC_FRAME_IS_SYNC_POINT (frame))
       buf->omx_buf->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
 
-    if (header)
+    if (header && !self->started)
       buf->omx_buf->nFlags |= OMX_BUFFERFLAG_CODECCONFIG;
 
     /* TODO: Set flags
diff --git a/omx/gstomxvideodec.h b/omx/gstomxvideodec.h
index df441d9..6ff873f 100644
--- a/omx/gstomxvideodec.h
+++ b/omx/gstomxvideodec.h
@@ -49,6 +49,28 @@ G_BEGIN_DECLS
 typedef struct _GstOMXVideoDec GstOMXVideoDec;
 typedef struct _GstOMXVideoDecClass GstOMXVideoDecClass;
 
+#ifndef GST_VIDEO_FLAG_ARM_AFBC
+#define GST_VIDEO_FLAG_ARM_AFBC (1UL << 31)
+#define GST_VIDEO_INFO_SET_AFBC(i) \
+  GST_VIDEO_INFO_FLAG_SET (i, GST_VIDEO_FLAG_ARM_AFBC)
+#define GST_VIDEO_INFO_UNSET_AFBC(i) \
+  GST_VIDEO_INFO_FLAG_UNSET (i, GST_VIDEO_FLAG_ARM_AFBC)
+#define GST_VIDEO_INFO_IS_AFBC(i) \
+  GST_VIDEO_INFO_FLAG_IS_SET (i, GST_VIDEO_FLAG_ARM_AFBC)
+#endif
+
+#ifndef GST_VIDEO_FLAG_10BIT_BUFFER
+#define GST_VIDEO_FLAG_10BIT_BUFFER (1UL << 30)
+#define GST_VIDEO_INFO_SET_10BIT_BUFFER(i) \
+  GST_VIDEO_INFO_FLAG_SET (i, GST_VIDEO_FLAG_10BIT_BUFFER)
+#define GST_VIDEO_INFO_UNSET_10BIT_BUFFER(i) \
+  GST_VIDEO_INFO_FLAG_UNSET (i, GST_VIDEO_FLAG_10BIT_BUFFER)
+#define GST_VIDEO_INFO_IS_10BIT_BUFFER(i) \
+  GST_VIDEO_INFO_FLAG_IS_SET (i, GST_VIDEO_FLAG_10BIT_BUFFER)
+#endif
+
+#define AW_OMX_FEATURE_ARM_AFBC "afbc"
+
 struct _GstOMXVideoDec
 {
   GstVideoDecoder parent;
@@ -100,6 +122,9 @@ struct _GstOMXVideoDec
 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
   guint32 internal_entropy_buffers;
 #endif
+  guint32 scale;
+  gboolean disable_dma_feature;
+  gboolean arm_afbc;
 };
 
 struct _GstOMXVideoDecClass
diff --git a/omx/gstomxvideoenc.c b/omx/gstomxvideoenc.c
index 6dbfb41..1f9231d 100644
--- a/omx/gstomxvideoenc.c
+++ b/omx/gstomxvideoenc.c
@@ -31,6 +31,7 @@
 #include "gstomxbufferpool.h"
 #include "gstomxvideo.h"
 #include "gstomxvideoenc.h"
+#include "AWOMX_VideoIndexExtension.h"
 
 #ifdef USE_OMX_TARGET_RPI
 #include <OMX_Broadcom.h>
@@ -283,6 +284,8 @@ enum
   PROP_LONGTERM_REF,
   PROP_LONGTERM_FREQUENCY,
   PROP_LOOK_AHEAD,
+  PROP_OUTPUT_WIDTH,
+  PROP_OUTPUT_HEIGHT,
 };
 
 /* FIXME: Better defaults */
@@ -315,6 +318,10 @@ enum
 #define OMX_ALG_GST_EVENT_INSERT_LONGTERM "omx-alg/insert-longterm"
 #define OMX_ALG_GST_EVENT_USE_LONGTERM "omx-alg/use-longterm"
 
+/* AW encoder output*/
+#define GST_OMX_VIDEO_ENC_OUTPUT_WIDTH 0
+#define GST_OMX_VIDEO_ENC_OUTPUT_HEIGHT 0
+
 /* class initialization */
 #define do_init \
 { \
@@ -326,6 +333,50 @@ enum
 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstOMXVideoEnc, gst_omx_video_enc,
     GST_TYPE_VIDEO_ENCODER, do_init);
 
+//AW CODE START
+//return valid fd if we support for zero-copy mode, else return -1
+static gint
+gst_is_gst_aw_buffer(GstBuffer *input)
+{
+  int fd = -1;
+
+  // set env variable to force using copy mode.
+  if(getenv("OMX_ENC_COPY_MODE"))
+    return fd;
+
+  if (!gst_is_dmabuf_memory (gst_buffer_peek_memory (input, 0))) {
+    GST_DEBUG_OBJECT (NULL, "input not dmabuf");
+  } else {
+    gint n_memory = gst_buffer_n_memory(input);
+    GST_DEBUG_OBJECT (NULL, "n_memory count = %d", n_memory);
+    if(n_memory > AW_ENC_MAX_PLANE_SIZE) {
+      GST_DEBUG_OBJECT(NULL, "only support %d fd for enc .vs current %d", AW_ENC_MAX_PLANE_SIZE, n_memory);
+    } else {
+      fd = gst_dmabuf_memory_get_fd(gst_buffer_peek_memory (input, 0));
+      GST_DEBUG_OBJECT(NULL, "getDmaBuf fd %d", fd);
+    }
+  }
+  return fd;
+}
+
+static guint64
+gst_is_buffer_has_phy(GstBuffer *input)
+{
+  GstCustomMeta *meta;
+  GstStructure *s;
+  guint64 addr = 0;
+
+  meta = gst_buffer_get_custom_meta (input, "GstAwMeta");
+  if (meta) {
+    s = gst_custom_meta_get_structure (meta);
+    gst_structure_get_uint64(s, "aw_buffer_phy", &addr);
+  }
+
+  return addr;
+}
+
+//AW CODE END
+
 static void
 gst_omx_video_enc_class_init (GstOMXVideoEncClass * klass)
 {
@@ -346,6 +397,18 @@ gst_omx_video_enc_class_init (GstOMXVideoEncClass * klass)
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
           GST_PARAM_MUTABLE_READY));
 
+  g_object_class_install_property (gobject_class, PROP_OUTPUT_WIDTH,
+      g_param_spec_uint ("output-width", "Output Width",
+          "the output pictrue width, 0 means same as input",
+          0, G_MAXUINT, GST_OMX_VIDEO_ENC_OUTPUT_WIDTH,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_OUTPUT_HEIGHT,
+      g_param_spec_uint ("output-height", "Output Height",
+          "the output pictrue height, 0 means same as input",
+          0, G_MAXUINT, GST_OMX_VIDEO_ENC_OUTPUT_HEIGHT,
+          G_PARAM_READWRITE));
+
   g_object_class_install_property (gobject_class, PROP_TARGET_BITRATE,
       g_param_spec_uint ("target-bitrate", "Target Bitrate",
           "Target bitrate in bits per second (0xffffffff=component default)",
@@ -545,6 +608,8 @@ gst_omx_video_enc_class_init (GstOMXVideoEncClass * klass)
 
   klass->cdata.type = GST_OMX_COMPONENT_TYPE_FILTER;
   klass->cdata.default_sink_template_caps =
+      GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_DMABUF,
+      GST_OMX_VIDEO_ENC_SUPPORTED_FORMATS) ";"
       GST_VIDEO_CAPS_MAKE (GST_OMX_VIDEO_ENC_SUPPORTED_FORMATS);
 
   klass->handle_output_frame =
@@ -582,6 +647,8 @@ gst_omx_video_enc_init (GstOMXVideoEnc * self)
 #endif
 
   self->default_target_bitrate = GST_OMX_PROP_OMX_DEFAULT;
+  self->out_frame_width = GST_OMX_VIDEO_ENC_OUTPUT_WIDTH;
+  self->out_frame_height = GST_OMX_VIDEO_ENC_OUTPUT_HEIGHT;
 
   g_mutex_init (&self->drain_lock);
   g_cond_init (&self->drain_cond);
@@ -1222,6 +1289,12 @@ gst_omx_video_enc_set_property (GObject * object, guint prop_id,
       self->look_ahead = g_value_get_uint (value);
       break;
 #endif
+    case PROP_OUTPUT_WIDTH:
+      self->out_frame_width = g_value_get_uint (value);
+      break;
+    case PROP_OUTPUT_HEIGHT:
+      self->out_frame_height = g_value_get_uint (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1311,6 +1384,12 @@ gst_omx_video_enc_get_property (GObject * object, guint prop_id, GValue * value,
       g_value_set_uint (value, self->look_ahead);
       break;
 #endif
+    case PROP_OUTPUT_WIDTH:
+      g_value_set_uint (value, self->out_frame_width);
+      break;
+    case PROP_OUTPUT_HEIGHT:
+      g_value_set_uint (value, self->out_frame_height);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1391,6 +1470,7 @@ get_chroma_info_from_input (GstOMXVideoEnc * self, const gchar ** chroma_format,
       break;
     case GST_VIDEO_FORMAT_I420:
     case GST_VIDEO_FORMAT_NV12:
+    case GST_VIDEO_FORMAT_NV21:
       *chroma_format = "4:2:0";
       *bit_depth_luma = *bit_depth_chroma = 8;
       break;
@@ -1474,6 +1554,14 @@ gst_omx_video_enc_handle_output_frame (GstOMXVideoEnc * self, GstOMXPort * port,
         gst_video_encoder_set_output_state (GST_VIDEO_ENCODER (self), caps,
         self->input_state);
     state->codec_data = codec_data;
+
+    if (self->out_frame_width > 0 && self->out_frame_height > 0)
+    {
+      GST_DEBUG_OBJECT (self, "Setting output state: %d x %d ", self->out_frame_width, self->out_frame_height);
+      state->info.width = self->out_frame_width;
+      state->info.height = self->out_frame_height;
+    }
+
     gst_video_codec_state_unref (state);
     if (!gst_video_encoder_negotiate (GST_VIDEO_ENCODER (self))) {
       gst_video_codec_frame_unref (frame);
@@ -1487,7 +1575,7 @@ gst_omx_video_enc_handle_output_frame (GstOMXVideoEnc * self, GstOMXPort * port,
     GstBuffer *outbuf;
     GstMapInfo map = GST_MAP_INFO_INIT;
 
-    GST_DEBUG_OBJECT (self, "Handling output data");
+    GST_DEBUG_OBJECT (self, "Handling output data pts %lld", buf->omx_buf->nTimeStamp);
 
     outbuf = gst_buffer_new_and_alloc (buf->omx_buf->nFilledLen);
 
@@ -1655,6 +1743,13 @@ gst_omx_video_enc_loop (GstOMXVideoEnc * self)
         self->input_state);
     gst_video_codec_state_unref (state);
 
+    if (self->out_frame_width > 0 && self->out_frame_height > 0)
+    {
+      GST_DEBUG_OBJECT (self, "Setting output state: %d x %d ", self->out_frame_width, self->out_frame_height);
+      state->info.width = self->out_frame_width;
+      state->info.height = self->out_frame_height;
+    }
+
     if (!gst_video_encoder_negotiate (GST_VIDEO_ENCODER (self))) {
       if (buf)
         gst_omx_port_release_buffer (self->enc_out_port, buf);
@@ -1985,6 +2080,7 @@ gst_omx_video_enc_configure_input_buffer (GstOMXVideoEnc * self,
   GstOMXVideoEncClass *klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
   GstVideoInfo *info = &self->input_state->info;
   OMX_PARAM_PORTDEFINITIONTYPE port_def;
+  OMX_AW_BUFFER_PARAM aw_param;
   GstVideoMeta *meta;
   guint stride, slice_height;
 
@@ -2016,6 +2112,46 @@ gst_omx_video_enc_configure_input_buffer (GstOMXVideoEnc * self,
     slice_height = GST_VIDEO_INFO_FIELD_HEIGHT (info);
   }
 
+  // AW CODE START
+  /* Get crop information from buffer if available (in case frames from hardware decoder) */
+  GstVideoCropMeta *crop_meta = gst_buffer_get_video_crop_meta (input);
+  if (crop_meta) {
+    /* Use crop information to set the actual frame dimensions */
+    OMX_CONFIG_RECTTYPE config;
+    OMX_ERRORTYPE err;
+
+    GST_OMX_INIT_STRUCT (&config);
+    config.nPortIndex = self->enc_out_port->index;
+    config.nLeft = 0;
+    config.nTop = 0;
+    config.nWidth = crop_meta->width;
+    config.nHeight = crop_meta->height;
+
+    err = gst_omx_component_set_config (self->enc,
+        OMX_IndexConfigCommonOutputCrop, &config);
+
+    GST_INFO_OBJECT (self,
+        "using crop information to output frame: %dx%d (input original: %dx%d)",
+        crop_meta->width, crop_meta->height,
+        port_def.format.video.nFrameWidth, port_def.format.video.nFrameHeight);
+  } else {
+    /* No crop information, use the original frame dimensions */
+    port_def.format.video.nFrameWidth = info->width;
+    port_def.format.video.nFrameHeight = GST_VIDEO_INFO_FIELD_HEIGHT (info);
+    GST_DEBUG_OBJECT (self,
+        "no crop information available, using original frame dimensions: %dx%d",
+        port_def.format.video.nFrameWidth, port_def.format.video.nFrameHeight);
+  }
+  // AW CODE END
+
+  if (gst_is_gst_aw_buffer(input) > 0) {
+    //GST_OMX_INIT_STRUCT(&aw_param);
+    aw_param.useAwBuffer = OMX_TRUE;
+    aw_param.nFdNum = gst_buffer_n_memory(input); //if dmabuf input, each memory contains one fd.
+    gst_omx_component_set_parameter(self->enc,
+      (OMX_INDEXTYPE)AWOMX_IndexVendorUseAwBuffer , &aw_param);
+  }
+
   if (port_def.nBufferAlignment)
     port_def.format.video.nStride =
         GST_ROUND_UP_N (stride, port_def.nBufferAlignment);
@@ -2027,9 +2163,18 @@ gst_omx_video_enc_configure_input_buffer (GstOMXVideoEnc * self,
   else
     port_def.format.video.nSliceHeight = slice_height;
 
+  //AW CODE START:
+  //hardware input buffer will set buffer align to 16. only use in copy mode.
+  if(gst_is_dmabuf_memory (gst_buffer_peek_memory (input, 0))) {
+    GST_DEBUG_OBJECT(self, "Hardware buffer in. Set slice height align to 16!");
+    port_def.format.video.nSliceHeight = GST_ROUND_UP_16 (slice_height);
+  }
+  //AW CODE END
+
   switch (port_def.format.video.eColorFormat) {
     case OMX_COLOR_FormatYUV420Planar:
     case OMX_COLOR_FormatYUV420PackedPlanar:
+    case OMX_COLOR_FormatYVU420Planar:
 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
       /* Formats defined in extensions have their own enum so disable to -Wswitch warning */
 #pragma GCC diagnostic push
@@ -2045,6 +2190,7 @@ gst_omx_video_enc_configure_input_buffer (GstOMXVideoEnc * self,
 
     case OMX_COLOR_FormatYUV420PackedSemiPlanar:
     case OMX_COLOR_FormatYUV420SemiPlanar:
+    case OMX_COLOR_FormatYVU420SemiPlanar:
       port_def.nBufferSize =
           (port_def.format.video.nStride * port_def.format.video.nFrameHeight) +
           (port_def.format.video.nStride *
@@ -2259,6 +2405,10 @@ gst_omx_video_enc_enable (GstOMXVideoEnc * self, GstBuffer * input)
 
   klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
 
+  if (gst_is_gst_aw_buffer(input) > 0) {
+    GST_INFO_OBJECT(self, "using zero copy mode for enc input");
+  }
+
   /* Is downstream using our buffer pool? */
   if (buffer_is_from_input_pool (self, input)) {
     self->in_pool_used = TRUE;
@@ -2525,6 +2675,9 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
       case GST_VIDEO_FORMAT_NV12:
         port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
         break;
+      case GST_VIDEO_FORMAT_NV21:
+        port_def.format.video.eColorFormat = OMX_COLOR_FormatYVU420SemiPlanar;
+        break;
       case GST_VIDEO_FORMAT_NV16:
         port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV422SemiPlanar;
         break;
@@ -2623,6 +2776,17 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
   if (gst_omx_port_update_port_definition (self->enc_out_port,
           NULL) != OMX_ErrorNone)
     return FALSE;
+
+  if (self->out_frame_width > 0 && self->out_frame_height > 0)
+  {
+    GST_DEBUG_OBJECT (self, "adding output size %d x %d", self->out_frame_width, self->out_frame_height);
+    self->enc_out_port->port_def.format.video.nFrameWidth = self->out_frame_width;
+    self->enc_out_port->port_def.format.video.nFrameHeight = self->out_frame_height;
+    if (gst_omx_port_update_port_definition (self->enc_out_port,
+            &(self->enc_out_port->port_def)) != OMX_ErrorNone)
+      return FALSE;
+  }
+
   if (gst_omx_port_update_port_definition (self->enc_in_port,
           NULL) != OMX_ErrorNone)
     return FALSE;
@@ -2777,6 +2941,7 @@ gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * inbuf,
   GstVideoFrame frame;
   GstVideoMeta *meta = gst_buffer_get_video_meta (inbuf);
   gint stride = meta ? meta->stride[0] : info->stride[0];
+  gint fd = -1;
 
   if (info->width != port_def->format.video.nFrameWidth ||
       GST_VIDEO_INFO_FIELD_HEIGHT (info) !=
@@ -2826,6 +2991,24 @@ gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * inbuf,
     goto done;
   }
 
+  fd = gst_is_gst_aw_buffer(inbuf);
+
+  if (fd > 0) {
+    guint64 phy_addr = 0;
+    GST_DEBUG_OBJECT(self, "using aw buffer fd %d", fd);
+    phy_addr = gst_is_buffer_has_phy(inbuf);
+    outbuf->omx_buf->nFilledLen = gst_buffer_get_size (inbuf);
+    if (outbuf->omx_buf->pPlatformPrivate) {
+      OmxPrivateBuffer *private = (OmxPrivateBuffer*) outbuf->omx_buf->pPlatformPrivate;
+      private->nShareBufFd = fd;
+      if (phy_addr) {
+        private->pAddrPhyY = (unsigned char*) phy_addr;
+      }
+      ret = TRUE;
+      goto done;
+    }
+  }
+
   /* Same strides and everything */
   if ((gst_buffer_get_size (inbuf) ==
           outbuf->omx_buf->nAllocLen - outbuf->omx_buf->nOffset) &&
@@ -2914,6 +3097,7 @@ gst_omx_video_enc_fill_buffer (GstOMXVideoEnc * self, GstBuffer * inbuf,
       break;
     }
     case GST_VIDEO_FORMAT_NV12:
+    case GST_VIDEO_FORMAT_NV21:
     case GST_VIDEO_FORMAT_NV16:
     case GST_VIDEO_FORMAT_NV12_10LE32:
     case GST_VIDEO_FORMAT_NV16_10LE32:
@@ -3213,6 +3397,14 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder,
       goto buffer_fill_error;
     }
 
+    /* No need to ref input frame because buffer will automatic reference if passed to omx component
+     * and unref it if we have filled the buffer done.
+    if (gst_is_gst_aw_buffer(frame->input_buffer) > 0 && buf->omx_buf->pPlatformPrivate) {
+      ((OmxPrivateBuffer*)(buf->omx_buf->pPlatformPrivate))->gstFrame = (void *) frame->input_buffer;
+      gst_buffer_ref(frame->input_buffer);
+      GST_DEBUG_OBJECT (self, "ref input frame %p", frame->input_buffer);
+    }*/
+
     timestamp = frame->pts;
     if (timestamp != GST_CLOCK_TIME_NONE) {
       GST_OMX_SET_TICKS (buf->omx_buf->nTimeStamp,
@@ -3544,10 +3736,12 @@ filter_supported_formats (GList * negotiation_map)
     switch (nmap->format) {
       case GST_VIDEO_FORMAT_I420:
       case GST_VIDEO_FORMAT_NV12:
+      case GST_VIDEO_FORMAT_NV21:
       case GST_VIDEO_FORMAT_NV12_10LE32:
       case GST_VIDEO_FORMAT_NV16:
       case GST_VIDEO_FORMAT_NV16_10LE32:
       case GST_VIDEO_FORMAT_GRAY8:
+      case GST_VIDEO_FORMAT_YV12:
         cur = g_list_next (cur);
         continue;
       default:
diff --git a/omx/gstomxvideoenc.h b/omx/gstomxvideoenc.h
index 51e2baf..128ba37 100644
--- a/omx/gstomxvideoenc.h
+++ b/omx/gstomxvideoenc.h
@@ -42,6 +42,12 @@ G_BEGIN_DECLS
 #define GST_IS_OMX_VIDEO_ENC_CLASS(obj) \
   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_VIDEO_ENC))
 
+
+//AW CODE START
+//currently we only support up to two plane buffers with fd input to the encoder
+#define AW_ENC_MAX_PLANE_SIZE     (2)
+//AW CODE END
+
 typedef struct _GstOMXVideoEnc GstOMXVideoEnc;
 typedef struct _GstOMXVideoEncClass GstOMXVideoEncClass;
 
@@ -113,6 +119,8 @@ struct _GstOMXVideoEnc
 #ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
   GEnumClass *alg_roi_quality_enum_class;
 #endif
+  guint out_frame_width;
+  guint out_frame_height;
 };
 
 struct _GstOMXVideoEncClass
diff --git a/omx/gstomxvp9dec.c b/omx/gstomxvp9dec.c
new file mode 100644
index 0000000..49a0c1c
--- /dev/null
+++ b/omx/gstomxvp9dec.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ *   Author: Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+
+#include "gstomxvp9dec.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_vp9_dec_debug_category);
+#define GST_CAT_DEFAULT gst_omx_vp9_dec_debug_category
+
+/* prototypes */
+static gboolean gst_omx_vp9_dec_is_format_change (GstOMXVideoDec * dec,
+    GstOMXPort * port, GstVideoCodecState * state);
+static gboolean gst_omx_vp9_dec_set_format (GstOMXVideoDec * dec,
+    GstOMXPort * port, GstVideoCodecState * state);
+
+enum
+{
+  PROP_0
+};
+
+/* class initialization */
+
+#define DEBUG_INIT \
+  GST_DEBUG_CATEGORY_INIT (gst_omx_vp9_dec_debug_category, "omxvp9dec", 0, \
+      "debug category for gst-omx video decoder base class");
+
+G_DEFINE_TYPE_WITH_CODE (GstOMXVP9Dec, gst_omx_vp9_dec,
+    GST_TYPE_OMX_VIDEO_DEC, DEBUG_INIT);
+
+static void
+gst_omx_vp9_dec_class_init (GstOMXVP9DecClass * klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstOMXVideoDecClass *videodec_class = GST_OMX_VIDEO_DEC_CLASS (klass);
+
+  videodec_class->is_format_change =
+      GST_DEBUG_FUNCPTR (gst_omx_vp9_dec_is_format_change);
+  videodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_vp9_dec_set_format);
+
+  videodec_class->cdata.default_sink_template_caps = "video/x-vp9, "
+	  "width=(int) [1,MAX], " "height=(int) [1,MAX]";
+
+  gst_element_class_set_static_metadata (element_class,
+      "OpenMAX VP9 Video Decoder",
+      "Codec/Decoder/Video",
+      "Decode VP9 video streams",
+      "Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>");
+
+  gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.vp9");
+}
+
+static void
+gst_omx_vp9_dec_init (GstOMXVP9Dec * self)
+{
+}
+
+static gboolean
+gst_omx_vp9_dec_is_format_change (GstOMXVideoDec * dec,
+    GstOMXPort * port, GstVideoCodecState * state)
+{
+  return FALSE;
+}
+
+static gboolean
+gst_omx_vp9_dec_set_format (GstOMXVideoDec * dec, GstOMXPort * port,
+    GstVideoCodecState * state)
+{
+  gboolean ret;
+  OMX_PARAM_PORTDEFINITIONTYPE port_def;
+
+  gst_omx_port_get_port_definition (port, &port_def);
+  port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingVP9;
+  ret = gst_omx_port_update_port_definition (port, &port_def) == OMX_ErrorNone;
+
+  return ret;
+}
diff --git a/omx/gstomxvp9dec.h b/omx/gstomxvp9dec.h
new file mode 100644
index 0000000..bb003c6
--- /dev/null
+++ b/omx/gstomxvp9dec.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ *   Author: Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation
+ * version 2.1 of the License.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#ifndef __GST_OMX_VP9_DEC_H__
+#define __GST_OMX_VP9_DEC_H__
+
+#include <gst/gst.h>
+#include "gstomxvideodec.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_OMX_VP9_DEC \
+  (gst_omx_vp9_dec_get_type())
+#define GST_OMX_VP9_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_VP9_DEC,GstOMXVP9Dec))
+#define GST_OMX_VP9_DEC_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_VP9_DEC,GstOMXVP9DecClass))
+#define GST_OMX_VP9_DEC_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_VP9_DEC,GstOMXVP9DecClass))
+#define GST_IS_OMX_VP9_DEC(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_VP9_DEC))
+#define GST_IS_OMX_VP9_DEC_CLASS(obj) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_VP9_DEC))
+
+typedef struct _GstOMXVP9Dec GstOMXVP9Dec;
+typedef struct _GstOMXVP9DecClass GstOMXVP9DecClass;
+
+struct _GstOMXVP9Dec
+{
+  GstOMXVideoDec parent;
+};
+
+struct _GstOMXVP9DecClass
+{
+  GstOMXVideoDecClass parent_class;
+};
+
+GType gst_omx_vp9_dec_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_VP9_DEC_H__ */
diff --git a/omx/gstomxwmvdec.c b/omx/gstomxwmvdec.c
index 1475827..b3bf42b 100644
--- a/omx/gstomxwmvdec.c
+++ b/omx/gstomxwmvdec.c
@@ -68,7 +68,7 @@ gst_omx_wmv_dec_class_init (GstOMXWMVDecClass * klass)
       "Decode WMV video streams",
       "Sebastian DrÃ¶ge <sebastian.droege@collabora.co.uk>");
 
-  gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.wmv");
+  gst_omx_set_default_role (&videodec_class->cdata, "video_decoder.vc1");
 }
 
 static void
diff --git a/omx/meson.build b/omx/meson.build
index becb72f..296ccf4 100644
--- a/omx/meson.build
+++ b/omx/meson.build
@@ -25,6 +25,11 @@ omx_sources = [
   'gstomxanalogaudiosink.c',
   'gstomxhdmiaudiosink.c',
   'gstomxmp3enc.c',
+  'gstomxavsdec.c',
+  'gstomxdivx4dec.c',
+  'gstomxdivxdec.c',
+  'gstomxmpeg1dec.c',
+  'gstomxmjpegenc.c'
 ]
 
 extra_c_args = []
@@ -33,6 +38,10 @@ if have_omx_vp8
   omx_sources += 'gstomxvp8dec.c'
 endif
 
+if have_omx_vp9
+  omx_sources += 'gstomxvp9dec.c'
+endif
+
 if have_omx_theora
   omx_sources += 'gstomxtheoradec.c'
 endif
@@ -60,4 +69,4 @@ gstomx = library('gstomx',
   install_dir : plugins_install_dir,
 )
 
-plugins = [gstomx]
\ No newline at end of file
+plugins = [gstomx]
diff --git a/omx/openmax/AWOMX_VideoIndexExtension.h b/omx/openmax/AWOMX_VideoIndexExtension.h
new file mode 100644
index 0000000..e7a91e3
--- /dev/null
+++ b/omx/openmax/AWOMX_VideoIndexExtension.h
@@ -0,0 +1,182 @@
+/*
+* Copyright (c) 2008-2016 Allwinner Technology Co. Ltd.
+* All rights reserved.
+*
+* File : AWOMX_VideoIndexExtension.h
+* Description :
+* History :
+*   Author  : AL3
+*   Date    : 2013/05/05
+*   Comment : complete the design code
+*/
+
+#ifndef _AWOMX_VIDEO_INDEX_EXTENSION_H_
+#define _AWOMX_VIDEO_INDEX_EXTENSION_H_
+
+/*========================================================================
+
+                     INCLUDE FILES FOR MODULE
+
+========================================================================== */
+#include <OMX_Core.h>
+
+/*========================================================================
+
+                      DEFINITIONS AND DECLARATIONS
+
+========================================================================== */
+
+#if defined( __cplusplus )
+extern "C"
+{
+#endif /* end of macro __cplusplus */
+
+#define OMX_VIDEO_PARAMS_EXTENDED_FLAGS_SCALING 1;
+#define OMX_VIDEO_PARAMS_EXTENDED_FLAGS_CROPPING 2;
+
+//* make  the struct standard after android5.1
+#ifdef CONF_LOLLIPOP_AND_NEWER
+typedef struct OMX_VIDEO_PARAMS_EXTENDED {
+     OMX_U32           nSize;
+     OMX_VERSIONTYPE   nVersion;
+     OMX_U32           ui32Flags;       // To check bEnableScaling and bEnableCropping enable or not
+     OMX_BOOL          bEnableScaling;  // Resolution Scaling
+     OMX_U16           ui16ScaledWidth; // pixel of width after scale
+     OMX_U16           ui16ScaledHeight;// pixel of height after scale
+     OMX_BOOL          bEnableCropping; // Resolution Cropping
+     OMX_U16           ui16CropLeft;    // Pixel of columns to be cropped from lefthand-side edge
+     OMX_U16           ui16CropRight;   // Pixel of columns to be cropped from righthand-side edge
+     OMX_U16           ui16CropTop;     // Pixel of rows to be cropped from the top edge
+     OMX_U16           ui16CropBottom;  // Pixel of rows to be cropped from the bottom edge
+} OMX_VIDEO_PARAMS_EXTENDED;
+#else
+typedef struct _OMX_VIDEO_PARAMS_EXTENDED {
+     OMX_U32         ui32Flags;
+     OMX_BOOL        bEnableScaling; // Resolution Scaling
+     OMX_U16         ui16ScaledWidth;
+     OMX_U16         ui16ScaledHeight;
+     OMX_BOOL        bEnableCropping; // Resolution Cropping
+     OMX_U16         ui16CropLeft;//Number of columns to be cropped from lefthand-side edge
+     OMX_U16         ui16CropRight;//Number of columns to be cropped from righthand-side edge
+     OMX_U16         ui16CropTop;//Number of rows to be cropped from the top edge
+     OMX_U16         ui16CropBottom;// Number of rows to be cropped from the bottom edge
+} OMX_VIDEO_PARAMS_EXTENDED;
+#endif
+
+
+typedef enum _OMX_VIDEO_SUPERFRAME_MODE {
+    OMX_VIDEO_SUPERFRAME_NONE,
+    OMX_VIDEO_SUPERFRAME_DISCARD,
+    OMX_VIDEO_SUPERFRAME_REENCODE,
+} OMX_VIDEO_SUPERFRAME_MODE;
+
+typedef struct _OMX_VIDEO_SUPER_FRAME {
+     OMX_BOOL                   bEnable;
+     OMX_VIDEO_SUPERFRAME_MODE  eSuperFrameMode;
+     OMX_U32                    nMaxIFrameBits;
+     OMX_U32                    nMaxPFrameBits;
+} OMX_VIDEO_PARAMS_SUPER_FRAME;
+
+typedef struct _OMX_VIDEO_MD {
+    OMX_BOOL   bMotionDetectEnable;
+    OMX_S32    nMotionDetectRatio;/* 0~12, advise set 0 */
+    OMX_S32    nStaticDetectRatio;/* 0~12, should be larger than nMotionDetectRatio,advise set 2 */
+    OMX_S32    nMaxNumStaticFrame;/* advise set 4 */
+    double     nStaticBitsRatio; /* advise set 0.2~0.3 at daytime, set 0.1 at night */
+    double     dMV64x64Ratio; /* advise set 0.01 */
+    OMX_S16    sMVXTh; /* advise set 6 */
+    OMX_S16    sMVYTh; /* advise set 6 */
+} OMX_VIDEO_PARAMS_MD;
+
+typedef struct _OMX_VIDEO_VBR {
+     OMX_BOOL        bEnable;
+     OMX_S32         uQpMin;
+     OMX_S32         uQpMax;
+     OMX_S32         uBitRate;
+     OMX_VIDEO_PARAMS_MD sMdParam;
+} OMX_VIDEO_PARAMS_VBR;
+
+//* The Amount of Temporal SVC Layers
+typedef enum {
+    OMX_VIDEO_NO_SVC = 0,
+    OMX_VIDEO_LAYER_2 = 2,
+    OMX_VIDEO_LAYER_3 = 3,
+    OMX_VIDEO_LAYER_4 = 4
+} OMX_VIDEO_LAYER;
+
+typedef struct _OMX_VIDEO_SVC {
+     OMX_BOOL               bEnable;
+     OMX_VIDEO_LAYER        eSvcLayer;
+     OMX_U32                uLayerRatio[4];
+} OMX_VIDEO_PARAMS_SVC;
+
+
+typedef struct VIDDEC_CUSTOM_PARAM
+{
+    unsigned char cCustomParamName[128];
+    OMX_INDEXTYPE nCustomParamIndex;
+} VIDDEC_CUSTOM_PARAM;
+
+
+typedef struct VIDEO_PROFILE_LEVEL
+{
+    OMX_S32  nProfile;
+    OMX_S32  nLevel;
+} VIDEO_PROFILE_LEVEL_TYPE;
+
+typedef struct OMX_AW_BUFFER_PARAM {
+    OMX_BOOL useAwBuffer;
+    OMX_U32  nFdNum; // maybe contain more than one fd in GstBuffer, indicate more than one plane.
+} OMX_AW_BUFFER_PARAM;
+
+/**
+ * Enumeration used to define Allwinner's vendor extensions for
+ * video. The video extensions occupy a range of
+ * 0x7F100000-0x7F1FFFFF, inclusive.
+ */
+
+typedef enum AW_VIDEO_EXTENSIONS_INDEXTYPE
+{
+    /* OMX.google.android.index.enableAndroidNativeBuffers */
+    AWOMX_IndexParamVideoEnableAndroidNativeBuffers    = 0x7F100000,
+    /* OMX.google.android.index.getAndroidNativeBufferUsage */
+    AWOMX_IndexParamVideoGetAndroidNativeBufferUsage   = 0x7F100001,
+    /* OMX.google.android.index.useAndroidNativeBuffer2 */
+    AWOMX_IndexParamVideoUseAndroidNativeBuffer2       = 0x7F100002,
+    AWOMX_IndexParamVideoUseStoreMetaDataInBuffer      = 0x7F100003,
+    AWOMX_IndexParamVideoUsePrepareForAdaptivePlayback = 0x7F100004,
+    AWOMX_IndexParamVideoGetAfbcHdrFlag                = 0x7F100005,
+    AWOMX_IndexParamVideoAllocateNativeHandle          = 0x7F100006,
+    AWOMX_IndexParamVideoDescribeColorAspects          = 0x7F100007,
+    AWOMX_IndexParamVideoDescribeHDRStaticInfo         = 0x7F100008,
+    AWOMX_IndexVendorUseAwBuffer                       = 0x7F100009,
+    AWOMX_IndexVendorSetScale                          = 0x7F100010,
+    AWOMX_IndexParamVideoSetAfbcHdrFlag                = 0x7F100011,
+    AWOMX_IndexVendorSetVencCsdMode                    = 0x7F100012,
+    AWOMX_IndexParamVideoUnused                        = 0x7F2FFFFF
+} AW_VIDEO_EXTENSIONS_INDEXTYPE;
+
+#define VIDDEC_CUSTOMPARAM_ENABLE_ANDROID_NATIVE_BUFFER  \
+        "OMX.google.android.index.enableAndroidNativeBuffers"
+#define VIDDEC_CUSTOMPARAM_GET_ANDROID_NATIVE_BUFFER_USAGE \
+        "OMX.google.android.index.getAndroidNativeBufferUsage"
+#define VIDDEC_CUSTOMPARAM_USE_ANDROID_NATIVE_BUFFER2 \
+        "OMX.google.android.index.useAndroidNativeBuffer2"
+#define VIDDEC_CUSTOMPARAM_STORE_META_DATA_IN_BUFFER  \
+        "OMX.google.android.index.storeMetaDataInBuffers"
+#define VIDDEC_CUSTOMPARAM_PREPARE_FOR_ADAPTIVE_PLAYBACK  \
+        "OMX.google.android.index.prepareForAdaptivePlayback"
+#define VIDDEC_CUSTOMPARAM_ALLOCATE_NATIVE_HANDLE \
+        "OMX.google.android.index.allocateNativeHandle"
+#define VIDDEC_CUSTOMPARAM_GET_AFBC_HDR_FLAG  \
+        "OMX.google.android.index.getAfbcHdrFlag"
+#define VIDDEC_CUSTOMPARAM_DESCRIBE_COLORASPECTS \
+        "OMX.google.android.index.describeColorAspects"
+#define VIDDEC_CUSTOMPARAM_DESCRIBE_HDR_STATIC_INFO \
+        "OMX.google.android.index.describeHDRStaticInfo"
+
+#if defined( __cplusplus )
+}
+#endif /* end of macro __cplusplus */
+
+#endif /* end of macro _AWOMX_VIDEO_INDEX_EXTENSION_H_ */
diff --git a/omx/openmax/OMX_IVCommon.h b/omx/openmax/OMX_IVCommon.h
index 4c4995c..7da2f48 100644
--- a/omx/openmax/OMX_IVCommon.h
+++ b/omx/openmax/OMX_IVCommon.h
@@ -130,8 +130,30 @@ typedef enum OMX_COLOR_FORMATTYPE {
     OMX_COLOR_Format18BitBGR666,
     OMX_COLOR_Format24BitARGB6666,
     OMX_COLOR_Format24BitABGR6666,
-    OMX_COLOR_FormatKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
-    OMX_COLOR_FormatVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+    /**< Reserved region for introducing Khronos Standard Extensions */
+    OMX_COLOR_FormatKhronosExtensions = 0x6F000000,
+    /**< Reserved region for introducing Vendor Extensions */
+    OMX_COLOR_FormatVendorStartUnused = 0x7F000000,
+    /**<Reserved android opaque colorformat. Tells the encoder that
+     * the actual colorformat will be  relayed by the
+     * Gralloc Buffers.
+     * FIXME: In the process of reserving some enum values for
+     * Android-specific OMX IL colorformats. Change this enum to
+     * an acceptable range once that is done.
+     * */
+
+    //* extended by aw;
+    OMX_COLOR_FormatYVU420SemiPlanar, //NV21
+    OMX_COLOR_FormatYVU420Planar,  //YV12
+    //* end;
+
+    OMX_COLOR_FormatAndroidOpaque = 0x7F000789,
+    OMX_COLOR_FormatYUV420Flexible = 0x7F420888,
+    OMX_TI_COLOR_FormatYUV420PackedSemiPlanar = 0x7F000100, //NV12
+    OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00,
+    OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka = 0x7FA30C03,
+    OMX_SEC_COLOR_FormatNV12Tiled = 0x7FC00002,
+    OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar32m = 0x7FA30C04,
     OMX_COLOR_FormatMax = 0x7FFFFFFF
 } OMX_COLOR_FORMATTYPE;
 
diff --git a/omx/openmax/OMX_Index.h b/omx/openmax/OMX_Index.h
index 44d4ea7..a30d267 100644
--- a/omx/openmax/OMX_Index.h
+++ b/omx/openmax/OMX_Index.h
@@ -245,7 +245,6 @@ typedef enum OMX_INDEXTYPE {
        to 0x7FFFFFFE.  This range is not broken out by vendor, so
        private indexes are not guaranteed unique and therefore should
        only be sent to the appropriate component. */
-
     OMX_IndexMax = 0x7FFFFFFF
 
 } OMX_INDEXTYPE;
diff --git a/omx/openmax/OMX_IndexExt.h b/omx/openmax/OMX_IndexExt.h
index 8d05faa..4021446 100644
--- a/omx/openmax/OMX_IndexExt.h
+++ b/omx/openmax/OMX_IndexExt.h
@@ -1,87 +1,113 @@
-/*
- * Copyright (c) 2010 The Khronos Group Inc. 
- * 
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject
- * to the following conditions: 
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software. 
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
- *
- */
-
-/** @file OMX_IndexExt.h - OpenMax IL version 1.1.2
- * The OMX_IndexExt header file contains extensions to the definitions 
- * for both applications and components .
- */
-
-#ifndef OMX_IndexExt_h
-#define OMX_IndexExt_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* Each OMX header shall include all required header files to allow the
- * header to compile without errors.  The includes below are required
- * for this header file to compile successfully
- */
-#include <OMX_Index.h>
-
-
-/** Khronos standard extension indices.
-
-This enum lists the current Khronos extension indices to OpenMAX IL.
-*/
-typedef enum OMX_INDEXEXTTYPE {
-
-    /* Component parameters and configurations */
-    OMX_IndexExtComponentStartUnused = OMX_IndexKhronosExtensions + 0x00100000,
-    OMX_IndexConfigCallbackRequest,                 /**< reference: OMX_CONFIG_CALLBACKREQUESTTYPE */
-    OMX_IndexConfigCommitMode,                      /**< reference: OMX_CONFIG_COMMITMODETYPE */
-    OMX_IndexConfigCommit,                          /**< reference: OMX_CONFIG_COMMITTYPE */
-
-    /* Port parameters and configurations */
-    OMX_IndexExtPortStartUnused = OMX_IndexKhronosExtensions + 0x00200000,
-
-    /* Audio parameters and configurations */
-    OMX_IndexExtAudioStartUnused = OMX_IndexKhronosExtensions + 0x00400000,
-
-    /* Image parameters and configurations */
-    OMX_IndexExtImageStartUnused = OMX_IndexKhronosExtensions + 0x00500000,
-
-    /* Video parameters and configurations */
-    OMX_IndexExtVideoStartUnused = OMX_IndexKhronosExtensions + 0x00600000,
-    OMX_IndexParamNalStreamFormatSupported,         /**< reference: OMX_NALSTREAMFORMATTYPE */
-    OMX_IndexParamNalStreamFormat,                  /**< reference: OMX_NALSTREAMFORMATTYPE */
-    OMX_IndexParamNalStreamFormatSelect,            /**< reference: OMX_NALSTREAMFORMATTYPE */
-
-    /* Image & Video common configurations */
-    OMX_IndexExtCommonStartUnused = OMX_IndexKhronosExtensions + 0x00700000,
-
-    /* Other configurations */
-    OMX_IndexExtOtherStartUnused = OMX_IndexKhronosExtensions + 0x00800000,
-
-    /* Time configurations */
-    OMX_IndexExtTimeStartUnused = OMX_IndexKhronosExtensions + 0x00900000,
-
-    OMX_IndexExtMax = 0x7FFFFFFF
-} OMX_INDEXEXTTYPE;
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* OMX_IndexExt_h */
-/* File EOF */
+/*
+ * Copyright (c) 2010 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/** @file OMX_IndexExt.h - OpenMax IL version 1.1.2
+ * The OMX_IndexExt header file contains extensions to the definitions
+ * for both applications and components .
+ */
+
+#ifndef OMX_IndexExt_h
+#define OMX_IndexExt_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Each OMX header shall include all required header files to allow the
+ * header to compile without errors.  The includes below are required
+ * for this header file to compile successfully
+ */
+#include <OMX_Index.h>
+
+
+/** Khronos standard extension indices.
+
+This enum lists the current Khronos extension indices to OpenMAX IL.
+*/
+typedef enum OMX_INDEXEXTTYPE {
+
+    /* Component parameters and configurations */
+    OMX_IndexExtComponentStartUnused = OMX_IndexKhronosExtensions + 0x00100000,
+    OMX_IndexConfigCallbackRequest,             /**< reference: OMX_CONFIG_CALLBACKREQUESTTYPE */
+    OMX_IndexConfigCommitMode,                  /**< reference: OMX_CONFIG_COMMITMODETYPE */
+    OMX_IndexConfigCommit,                      /**< reference: OMX_CONFIG_COMMITTYPE */
+
+    /* Port parameters and configurations */
+    OMX_IndexExtPortStartUnused = OMX_IndexKhronosExtensions + 0x00200000,
+
+    /* Audio parameters and configurations */
+    OMX_IndexExtAudioStartUnused = OMX_IndexKhronosExtensions + 0x00400000,
+    OMX_IndexParamAudioAndroidAc3,           /**< reference: OMX_AUDIO_PARAM_ANDROID_AC3TYPE */
+    OMX_IndexParamAudioAndroidOpus,          /**< reference: OMX_AUDIO_PARAM_ANDROID_OPUSTYPE */
+    /**< reference: OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE */
+    OMX_IndexParamAudioAndroidAacPresentation,
+    OMX_IndexParamAudioAndroidEac3,          /**< reference: OMX_AUDIO_PARAM_ANDROID_EAC3TYPE */
+    /**< reference: OMX_AUDIO_PARAM_ANDROID_PROFILETYPE */
+    OMX_IndexParamAudioProfileQuerySupported,
+
+    /* Image parameters and configurations */
+    OMX_IndexExtImageStartUnused = OMX_IndexKhronosExtensions + 0x00500000,
+
+    /* Video parameters and configurations */
+    OMX_IndexExtVideoStartUnused = OMX_IndexKhronosExtensions + 0x00600000,
+    OMX_IndexParamNalStreamFormatSupported,         /**< reference: OMX_NALSTREAMFORMATTYPE */
+    OMX_IndexParamNalStreamFormat,                  /**< reference: OMX_NALSTREAMFORMATTYPE */
+    OMX_IndexParamNalStreamFormatSelect,            /**< reference: OMX_NALSTREAMFORMATTYPE */
+    OMX_IndexParamVideoVp8,                         /**< reference: OMX_VIDEO_PARAM_VP8TYPE */
+    OMX_IndexConfigVideoVp8ReferenceFrame,      /**< reference: OMX_VIDEO_VP8REFERENCEFRAMETYPE */
+    /**< reference: OMX_VIDEO_VP8REFERENCEFRAMEINFOTYPE */
+    OMX_IndexConfigVideoVp8ReferenceFrameType,
+    /**< reference: OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE */
+    OMX_IndexParamVideoAndroidVp8Encoder,
+    OMX_IndexParamVideoHevc,                        /**< reference: OMX_VIDEO_PARAM_HEVCTYPE */
+    OMX_IndexParamSliceSegments,                    /**< reference: OMX_VIDEO_SLICESEGMENTSTYPE */
+    /**< reference: OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE */
+    OMX_IndexConfigAndroidIntraRefresh,
+    /**< reference: OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE */
+    OMX_IndexParamAndroidVideoTemporalLayering,
+    /**< reference: OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE */
+    OMX_IndexConfigAndroidVideoTemporalLayering,
+
+    /* Image & Video common configurations */
+    OMX_IndexExtCommonStartUnused = OMX_IndexKhronosExtensions + 0x00700000,
+
+    /* Other configurations */
+    OMX_IndexExtOtherStartUnused = OMX_IndexKhronosExtensions + 0x00800000,
+    OMX_IndexConfigAutoFramerateConversion,         /**< reference: OMX_CONFIG_BOOLEANTYPE */
+    OMX_IndexConfigPriority,                        /**< reference: OMX_PARAM_U32TYPE */
+    /**< reference: OMX_PARAM_U32TYPE in Q16 format for video and in Hz for audio */
+    OMX_IndexConfigOperatingRate,
+    OMX_IndexParamConsumerUsageBits,                /**< reference: OMX_PARAM_U32TYPE */
+
+    /* Time configurations */
+    OMX_IndexExtTimeStartUnused = OMX_IndexKhronosExtensions + 0x00900000,
+
+    OMX_IndexExtMax = 0x7FFFFFFF
+} OMX_INDEXEXTTYPE;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* OMX_IndexExt_h */
+/* File EOF */
diff --git a/omx/openmax/OMX_Other.h b/omx/openmax/OMX_Other.h
index caf7f38..853179c 100644
--- a/omx/openmax/OMX_Other.h
+++ b/omx/openmax/OMX_Other.h
@@ -90,9 +90,9 @@ typedef struct OMX_TIME_CONFIG_SEEKMODETYPE {
 /** Structure representing a time stamp used with the following configs 
  * on the Clock Component (CC):
  * 
- * OMX_IndexConfigTimeCurrentWallTime: query of the CC’s current wall  
+ * OMX_IndexConfigTimeCurrentWallTime: query of the CCï¿½s current wall  
  *     time
- * OMX_IndexConfigTimeCurrentMediaTime: query of the CC’s current media
+ * OMX_IndexConfigTimeCurrentMediaTime: query of the CCï¿½s current media
  *     time
  * OMX_IndexConfigTimeCurrentAudioReference and  
  * OMX_IndexConfigTimeCurrentVideoReference: audio/video reference 
@@ -103,7 +103,7 @@ typedef struct OMX_TIME_CONFIG_SEEKMODETYPE {
  *     OMX_BUFFERFLAG_STARTTIME set. It must use the timestamp
  *     specified by that buffer for nStartTimestamp. 
  *
- * It’s also used with the following config on components in general:
+ * Itï¿½s also used with the following config on components in general:
  *
  * OMX_IndexConfigTimePosition: IL client querying component position 
  * (GetConfig) or commanding a component to seek to the given location
@@ -247,7 +247,7 @@ typedef struct OMX_TIME_CONFIG_SCALETYPE {
                                      * scaling the media time */
 } OMX_TIME_CONFIG_SCALETYPE;
  
-/** Bits used to identify a clock port. Used in OMX_TIME_CONFIG_CLOCKSTATETYPE’s nWaitMask field */
+/** Bits used to identify a clock port. Used in OMX_TIME_CONFIG_CLOCKSTATETYPEï¿½s nWaitMask field */
 #define OMX_CLOCKPORT0 0x00000001
 #define OMX_CLOCKPORT1 0x00000002
 #define OMX_CLOCKPORT2 0x00000004
diff --git a/omx/openmax/OMX_Video.h b/omx/openmax/OMX_Video.h
index 163e450..2786a71 100644
--- a/omx/openmax/OMX_Video.h
+++ b/omx/openmax/OMX_Video.h
@@ -48,6 +48,16 @@ extern "C" {
 
 #include <OMX_IVCommon.h>
 
+#define AW_VIDEO_AFBC_FLAG  (0x01)
+#define AW_VIDEO_HDR_FLAG   (0x02)
+#define AW_VIDEO_10BIT_FLAG (0x04)
+
+//* extend by aw
+typedef struct AW_OMX_VIDEO_HDR_INFO{
+    OMX_U32 nExtVideoFullRangeFlag;
+    OMX_U32 nExtTransferCharacteristics;
+    OMX_U32 nExtMatrixCoeffs;
+}AW_OMX_VIDEO_HDR_INFO;
 
 /**
  * Enumeration used to define the possible video compression codings.  
@@ -68,8 +78,29 @@ typedef enum OMX_VIDEO_CODINGTYPE {
     OMX_VIDEO_CodingRV,         /**< all versions of Real Video */
     OMX_VIDEO_CodingAVC,        /**< H.264/AVC */
     OMX_VIDEO_CodingMJPEG,      /**< Motion JPEG */
+    OMX_VIDEO_CodingVP8,        /**< Google VP8, formerly known as On2 VP8 */
+    OMX_VIDEO_CodingVP9,        /**< Google VP9 */
+    OMX_VIDEO_CodingHEVC,       /**< ITU H.265/HEVC */
+
     OMX_VIDEO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */ 
     OMX_VIDEO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
+
+    //*add by xiwang
+    OMX_VIDEO_CodingVP6,
+    OMX_VIDEO_CodingMPEG1,
+    OMX_VIDEO_CodingS263,
+    OMX_VIDEO_CodingMSMPEG4V1,
+    OMX_VIDEO_CodingMSMPEG4V2,
+    OMX_VIDEO_CodingDIVX,
+    OMX_VIDEO_CodingXVID,
+    OMX_VIDEO_CodingRXG2,
+    OMX_VIDEO_CodingWMV1,
+    OMX_VIDEO_CodingWMV2,
+    OMX_VIDEO_CodingMSMPEG4V3,
+	OMX_VIDEO_CodingDIVX4,
+	OMX_VIDEO_CodingRX,
+	OMX_VIDEO_CodingAVS,
+
     OMX_VIDEO_CodingMax = 0x7FFFFFFF
 } OMX_VIDEO_CODINGTYPE;
 
diff --git a/omx/openmax/OMX_VideoExt.h b/omx/openmax/OMX_VideoExt.h
index a9b5d45..2c02431 100644
--- a/omx/openmax/OMX_VideoExt.h
+++ b/omx/openmax/OMX_VideoExt.h
@@ -1,69 +1,401 @@
-/*
- * Copyright (c) 2010 The Khronos Group Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject
- * to the following conditions:
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-/** OMX_VideoExt.h - OpenMax IL version 1.1.2
- * The OMX_VideoExt header file contains extensions to the
- * definitions used by both the application and the component to
- * access video items.
- */
-
-#ifndef OMX_VideoExt_h
-#define OMX_VideoExt_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* Each OMX header shall include all required header files to allow the
- * header to compile without errors.  The includes below are required
- * for this header file to compile successfully
- */
-#include <OMX_Core.h>
-
-/** NALU Formats */
-typedef enum OMX_NALUFORMATSTYPE {
-    OMX_NaluFormatStartCodes = 1,
-    OMX_NaluFormatOneNaluPerBuffer = 2,
-    OMX_NaluFormatOneByteInterleaveLength = 4,
-    OMX_NaluFormatTwoByteInterleaveLength = 8,
-    OMX_NaluFormatFourByteInterleaveLength = 16,
-    OMX_NaluFormatCodingMax = 0x7FFFFFFF
-} OMX_NALUFORMATSTYPE;
-
-
-/** NAL Stream Format */
-typedef struct OMX_NALSTREAMFORMATTYPE{
-    OMX_U32 nSize;
-    OMX_VERSIONTYPE nVersion;
-    OMX_U32 nPortIndex;
-    OMX_NALUFORMATSTYPE eNaluFormat;
-} OMX_NALSTREAMFORMATTYPE;
-
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* OMX_VideoExt_h */
-/* File EOF */
+/*
+ * Copyright (c) 2010 The Khronos Group Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject
+ * to the following conditions:
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/** OMX_VideoExt.h - OpenMax IL version 1.1.2
+ * The OMX_VideoExt header file contains extensions to the
+ * definitions used by both the application and the component to
+ * access video items.
+ */
+
+#ifndef OMX_VideoExt_h
+#define OMX_VideoExt_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Each OMX header shall include all required header files to allow the
+ * header to compile without errors.  The includes below are required
+ * for this header file to compile successfully
+ */
+#include <OMX_Core.h>
+
+/** NALU Formats */
+typedef enum OMX_NALUFORMATSTYPE {
+    OMX_NaluFormatStartCodes = 1,
+    OMX_NaluFormatOneNaluPerBuffer = 2,
+    OMX_NaluFormatOneByteInterleaveLength = 4,
+    OMX_NaluFormatTwoByteInterleaveLength = 8,
+    OMX_NaluFormatFourByteInterleaveLength = 16,
+    OMX_NaluFormatCodingMax = 0x7FFFFFFF
+} OMX_NALUFORMATSTYPE;
+
+/** NAL Stream Format */
+typedef struct OMX_NALSTREAMFORMATTYPE{
+    OMX_U32 nSize;
+    OMX_VERSIONTYPE nVersion;
+    OMX_U32 nPortIndex;
+    OMX_NALUFORMATSTYPE eNaluFormat;
+} OMX_NALSTREAMFORMATTYPE;
+
+/** VP8 profiles */
+typedef enum OMX_VIDEO_VP8PROFILETYPE {
+    OMX_VIDEO_VP8ProfileMain = 0x01,
+    OMX_VIDEO_VP8ProfileUnknown = 0x6EFFFFFF,
+    OMX_VIDEO_VP8ProfileMax = 0x7FFFFFFF
+} OMX_VIDEO_VP8PROFILETYPE;
+
+/** VP8 levels */
+typedef enum OMX_VIDEO_VP8LEVELTYPE {
+    OMX_VIDEO_VP8Level_Version0 = 0x01,
+    OMX_VIDEO_VP8Level_Version1 = 0x02,
+    OMX_VIDEO_VP8Level_Version2 = 0x04,
+    OMX_VIDEO_VP8Level_Version3 = 0x08,
+    OMX_VIDEO_VP8LevelUnknown = 0x6EFFFFFF,
+    OMX_VIDEO_VP8LevelMax = 0x7FFFFFFF
+} OMX_VIDEO_VP8LEVELTYPE;
+
+/** VP9 profiles */
+typedef enum OMX_VIDEO_VP9PROFILETYPE {
+    OMX_VIDEO_VP9Profile0       = 0x1,
+    OMX_VIDEO_VP9Profile1       = 0x2,
+    OMX_VIDEO_VP9Profile2       = 0x4,
+    OMX_VIDEO_VP9Profile3       = 0x8,
+    // HDR profiles also support passing HDR metadata
+    OMX_VIDEO_VP9Profile2HDR    = 0x1000,
+    OMX_VIDEO_VP9Profile3HDR    = 0x2000,
+    OMX_VIDEO_VP9ProfileUnknown = 0x6EFFFFFF,
+    OMX_VIDEO_VP9ProfileMax     = 0x7FFFFFFF
+} OMX_VIDEO_VP9PROFILETYPE;
+
+/** VP9 levels */
+typedef enum OMX_VIDEO_VP9LEVELTYPE {
+    OMX_VIDEO_VP9Level1       = 0x1,
+    OMX_VIDEO_VP9Level11      = 0x2,
+    OMX_VIDEO_VP9Level2       = 0x4,
+    OMX_VIDEO_VP9Level21      = 0x8,
+    OMX_VIDEO_VP9Level3       = 0x10,
+    OMX_VIDEO_VP9Level31      = 0x20,
+    OMX_VIDEO_VP9Level4       = 0x40,
+    OMX_VIDEO_VP9Level41      = 0x80,
+    OMX_VIDEO_VP9Level5       = 0x100,
+    OMX_VIDEO_VP9Level51      = 0x200,
+    OMX_VIDEO_VP9Level52      = 0x400,
+    OMX_VIDEO_VP9Level6       = 0x800,
+    OMX_VIDEO_VP9Level61      = 0x1000,
+    OMX_VIDEO_VP9Level62      = 0x2000,
+    OMX_VIDEO_VP9LevelUnknown = 0x6EFFFFFF,
+    OMX_VIDEO_VP9LevelMax     = 0x7FFFFFFF
+} OMX_VIDEO_VP9LEVELTYPE;
+
+/** VP8 Param */
+typedef struct OMX_VIDEO_PARAM_VP8TYPE {
+    OMX_U32 nSize;
+    OMX_VERSIONTYPE nVersion;
+    OMX_U32 nPortIndex;
+    OMX_VIDEO_VP8PROFILETYPE eProfile;
+    OMX_VIDEO_VP8LEVELTYPE eLevel;
+    OMX_U32 nDCTPartitions;
+    OMX_BOOL bErrorResilientMode;
+} OMX_VIDEO_PARAM_VP8TYPE;
+
+/** Structure for configuring VP8 reference frames */
+typedef struct OMX_VIDEO_VP8REFERENCEFRAMETYPE {
+    OMX_U32 nSize;
+    OMX_VERSIONTYPE nVersion;
+    OMX_U32 nPortIndex;
+    OMX_BOOL bPreviousFrameRefresh;
+    OMX_BOOL bGoldenFrameRefresh;
+    OMX_BOOL bAlternateFrameRefresh;
+    OMX_BOOL bUsePreviousFrame;
+    OMX_BOOL bUseGoldenFrame;
+    OMX_BOOL bUseAlternateFrame;
+} OMX_VIDEO_VP8REFERENCEFRAMETYPE;
+
+/** Structure for querying VP8 reference frame type */
+typedef struct OMX_VIDEO_VP8REFERENCEFRAMEINFOTYPE {
+    OMX_U32 nSize;
+    OMX_VERSIONTYPE nVersion;
+    OMX_U32 nPortIndex;
+    OMX_BOOL bIsIntraFrame;
+    OMX_BOOL bIsGoldenOrAlternateFrame;
+} OMX_VIDEO_VP8REFERENCEFRAMEINFOTYPE;
+
+/** Maximum number of VP8 temporal layers */
+#define OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS 3
+
+/** VP8 temporal layer patterns */
+typedef enum OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE {
+    OMX_VIDEO_VPXTemporalLayerPatternNone = 0,
+    OMX_VIDEO_VPXTemporalLayerPatternWebRTC = 1,
+    OMX_VIDEO_VPXTemporalLayerPatternMax = 0x7FFFFFFF
+} OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE;
+
+/**
+ * Android specific VP8 encoder params
+ *
+ * STRUCT MEMBERS:
+ *  nSize                      : Size of the structure in bytes
+ *  nVersion                   : OMX specification version information
+ *  nPortIndex                 : Port that this structure applies to
+ *  nKeyFrameInterval          : Key frame interval in frames
+ *  eTemporalPattern           : Type of temporal layer pattern
+ *  nTemporalLayerCount        : Number of temporal coding layers
+ *  nTemporalLayerBitrateRatio : Bitrate ratio allocation between temporal
+ *                               streams in percentage
+ *  nMinQuantizer              : Minimum (best quality) quantizer
+ *  nMaxQuantizer              : Maximum (worst quality) quantizer
+ */
+typedef struct OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE {
+    OMX_U32 nSize;
+    OMX_VERSIONTYPE nVersion;
+    OMX_U32 nPortIndex;
+    OMX_U32 nKeyFrameInterval;        // distance between consecutive key_frames (including one
+                                      // of the key_frames). 0 means interval is unspecified and
+                                      // can be freely chosen by the codec. 1 means a stream of
+                                      // only key_frames.
+
+    OMX_VIDEO_ANDROID_VPXTEMPORALLAYERPATTERNTYPE eTemporalPattern;
+    OMX_U32 nTemporalLayerCount;
+    OMX_U32 nTemporalLayerBitrateRatio[OMX_VIDEO_ANDROID_MAXVP8TEMPORALLAYERS];
+    OMX_U32 nMinQuantizer;
+    OMX_U32 nMaxQuantizer;
+} OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE;
+
+/** HEVC Profile enum type */
+typedef enum OMX_VIDEO_HEVCPROFILETYPE {
+    OMX_VIDEO_HEVCProfileUnknown      = 0x0,
+    OMX_VIDEO_HEVCProfileMain         = 0x1,
+    OMX_VIDEO_HEVCProfileMain10       = 0x2,
+    // Main10 profile with HDR SEI support.
+    OMX_VIDEO_HEVCProfileMain10HDR10  = 0x1000,
+    OMX_VIDEO_HEVCProfileMax          = 0x7FFFFFFF
+} OMX_VIDEO_HEVCPROFILETYPE;
+
+/** HEVC Level enum type */
+typedef enum OMX_VIDEO_HEVCLEVELTYPE {
+    OMX_VIDEO_HEVCLevelUnknown    = 0x0,
+    OMX_VIDEO_HEVCMainTierLevel1  = 0x1,
+    OMX_VIDEO_HEVCHighTierLevel1  = 0x2,
+    OMX_VIDEO_HEVCMainTierLevel2  = 0x4,
+    OMX_VIDEO_HEVCHighTierLevel2  = 0x8,
+    OMX_VIDEO_HEVCMainTierLevel21 = 0x10,
+    OMX_VIDEO_HEVCHighTierLevel21 = 0x20,
+    OMX_VIDEO_HEVCMainTierLevel3  = 0x40,
+    OMX_VIDEO_HEVCHighTierLevel3  = 0x80,
+    OMX_VIDEO_HEVCMainTierLevel31 = 0x100,
+    OMX_VIDEO_HEVCHighTierLevel31 = 0x200,
+    OMX_VIDEO_HEVCMainTierLevel4  = 0x400,
+    OMX_VIDEO_HEVCHighTierLevel4  = 0x800,
+    OMX_VIDEO_HEVCMainTierLevel41 = 0x1000,
+    OMX_VIDEO_HEVCHighTierLevel41 = 0x2000,
+    OMX_VIDEO_HEVCMainTierLevel5  = 0x4000,
+    OMX_VIDEO_HEVCHighTierLevel5  = 0x8000,
+    OMX_VIDEO_HEVCMainTierLevel51 = 0x10000,
+    OMX_VIDEO_HEVCHighTierLevel51 = 0x20000,
+    OMX_VIDEO_HEVCMainTierLevel52 = 0x40000,
+    OMX_VIDEO_HEVCHighTierLevel52 = 0x80000,
+    OMX_VIDEO_HEVCMainTierLevel6  = 0x100000,
+    OMX_VIDEO_HEVCHighTierLevel6  = 0x200000,
+    OMX_VIDEO_HEVCMainTierLevel61 = 0x400000,
+    OMX_VIDEO_HEVCHighTierLevel61 = 0x800000,
+    OMX_VIDEO_HEVCMainTierLevel62 = 0x1000000,
+    OMX_VIDEO_HEVCHighTierLevel62 = 0x2000000,
+    OMX_VIDEO_HEVCHighTiermax     = 0x7FFFFFFF
+} OMX_VIDEO_HEVCLEVELTYPE;
+
+/** Structure for controlling HEVC video encoding */
+typedef struct OMX_VIDEO_PARAM_HEVCTYPE {
+    OMX_U32 nSize;
+    OMX_VERSIONTYPE nVersion;
+    OMX_U32 nPortIndex;
+    OMX_VIDEO_HEVCPROFILETYPE eProfile;
+    OMX_VIDEO_HEVCLEVELTYPE eLevel;
+    OMX_U32 nKeyFrameInterval;        // distance between consecutive I-frames (including one
+                                      // of the I frames). 0 means interval is unspecified and
+                                      // can be freely chosen by the codec. 1 means a stream of
+                                      // only I frames.
+} OMX_VIDEO_PARAM_HEVCTYPE;
+
+/** Structure to define if dependent slice segments should be used */
+typedef struct OMX_VIDEO_SLICESEGMENTSTYPE {
+    OMX_U32 nSize;
+    OMX_VERSIONTYPE nVersion;
+    OMX_U32 nPortIndex;
+    OMX_BOOL bDepedentSegments;
+    OMX_BOOL bEnableLoopFilterAcrossSlices;
+} OMX_VIDEO_SLICESEGMENTSTYPE;
+
+/** Structure to return timestamps of rendered output frames as well as EOS
+ *  for tunneled components.
+ */
+typedef struct OMX_VIDEO_RENDEREVENTTYPE {
+    OMX_S64 nMediaTimeUs;  // timestamp of rendered video frame
+    OMX_S64 nSystemTimeNs; // system monotonic time at the time frame was rendered
+                           // Use INT64_MAX for nMediaTimeUs to signal that the EOS
+                           // has been reached. In this case, nSystemTimeNs MUST be
+                           // the system time when the last frame was rendered.
+                           // This MUST be done in addition to returning (and
+                           // following) the render information for the last frame.
+} OMX_VIDEO_RENDEREVENTTYPE;
+
+/** Dolby Vision Profile enum type */
+typedef enum OMX_VIDEO_DOLBYVISIONPROFILETYPE {
+    OMX_VIDEO_DolbyVisionProfileUnknown = 0x0,
+    OMX_VIDEO_DolbyVisionProfileDvavPer = 0x1,
+    OMX_VIDEO_DolbyVisionProfileDvavPen = 0x2,
+    OMX_VIDEO_DolbyVisionProfileDvheDer = 0x4,
+    OMX_VIDEO_DolbyVisionProfileDvheDen = 0x8,
+    OMX_VIDEO_DolbyVisionProfileDvheDtr = 0x10,
+    OMX_VIDEO_DolbyVisionProfileDvheStn = 0x20,
+    OMX_VIDEO_DolbyVisionProfileDvheDth = 0x40,
+    OMX_VIDEO_DolbyVisionProfileDvheDtb = 0x80,
+    OMX_VIDEO_DolbyVisionProfileMax     = 0x7FFFFFFF
+} OMX_VIDEO_DOLBYVISIONPROFILETYPE;
+
+/** Dolby Vision Level enum type */
+typedef enum OMX_VIDEO_DOLBYVISIONLEVELTYPE {
+    OMX_VIDEO_DolbyVisionLevelUnknown = 0x0,
+    OMX_VIDEO_DolbyVisionLevelHd24    = 0x1,
+    OMX_VIDEO_DolbyVisionLevelHd30    = 0x2,
+    OMX_VIDEO_DolbyVisionLevelFhd24   = 0x4,
+    OMX_VIDEO_DolbyVisionLevelFhd30   = 0x8,
+    OMX_VIDEO_DolbyVisionLevelFhd60   = 0x10,
+    OMX_VIDEO_DolbyVisionLevelUhd24   = 0x20,
+    OMX_VIDEO_DolbyVisionLevelUhd30   = 0x40,
+    OMX_VIDEO_DolbyVisionLevelUhd48   = 0x80,
+    OMX_VIDEO_DolbyVisionLevelUhd60   = 0x100,
+    OMX_VIDEO_DolbyVisionLevelmax     = 0x7FFFFFFF
+} OMX_VIDEO_DOLBYVISIONLEVELTYPE;
+
+/**
+ * Structure for configuring video compression intra refresh period
+ *
+ * STRUCT MEMBERS:
+ *  nSize               : Size of the structure in bytes
+ *  nVersion            : OMX specification version information
+ *  nPortIndex          : Port that this structure applies to
+ *  nRefreshPeriod      : Intra refreh period in frames. Value 0 means disable intra refresh
+ */
+typedef struct OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE {
+    OMX_U32 nSize;
+    OMX_VERSIONTYPE nVersion;
+    OMX_U32 nPortIndex;
+    OMX_U32 nRefreshPeriod;
+} OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE;
+
+/** Maximum number of temporal layers supported by AVC/HEVC */
+#define OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS 8
+
+/** temporal layer patterns */
+typedef enum OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE {
+    OMX_VIDEO_AndroidTemporalLayeringPatternNone = 0,
+    // pattern as defined by WebRTC
+    OMX_VIDEO_AndroidTemporalLayeringPatternWebRTC = 1 << 0,
+    // pattern where frames in any layer other than the base layer only depend on at most the very
+    // last frame from each preceding layer (other than the base layer.)
+    OMX_VIDEO_AndroidTemporalLayeringPatternAndroid = 1 << 1,
+} OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE;
+
+/**
+ * Android specific param for configuration of temporal layering.
+ * Android only supports temporal layering where successive layers each double the
+ * previous layer's framerate.
+ * NOTE: Reading this parameter at run-time SHALL return actual run-time values.
+ *
+ *  nSize                      : Size of the structure in bytes
+ *  nVersion                   : OMX specification version information
+ *  nPortIndex                 : Port that this structure applies to (output port for encoders)
+ *  eSupportedPatterns         : A bitmask of supported layering patterns
+ *  nLayerCountMax             : Max number of temporal coding layers supported
+ *                               by the encoder (must be at least 1, 1 meaning temporal layering
+ *                               is NOT supported)
+ *  nBLayerCountMax            : Max number of layers that can contain B frames
+ *                               (0) to (nLayerCountMax - 1)
+ *  ePattern                   : Layering pattern.
+ *  nPLayerCountActual         : Number of temporal layers to be coded with non-B frames,
+ *                               starting from and including the base-layer.
+ *                               (1 to nLayerCountMax - nBLayerCountActual)
+ *                               If nPLayerCountActual is 1 and nBLayerCountActual is 0, temporal
+ *                               layering is disabled. Otherwise, it is enabled.
+ *  nBLayerCountActual         : Number of temporal layers to be coded with B frames,
+ *                               starting after non-B layers.
+ *                               (0 to nBLayerCountMax)
+ *  bBitrateRatiosSpecified    : Flag to indicate if layer-wise bitrate
+ *                               distribution is specified.
+ *  nBitrateRatios             : Bitrate ratio (100 based) per layer (index 0 is base layer).
+ *                               Honored if bBitrateRatiosSpecified is set.
+ *                               i.e for 4 layers with desired distribution (25% 25% 25% 25%),
+ *                               nBitrateRatio = {25, 50, 75, 100, ... }
+ *                               Values in indices not less than 'the actual number of layers
+ *                               minus 1' MAY be ignored and assumed to be 100.
+ */
+typedef struct OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE {
+    OMX_U32 nSize;
+    OMX_VERSIONTYPE nVersion;
+    OMX_U32 nPortIndex;
+    OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE eSupportedPatterns;
+    OMX_U32 nLayerCountMax;
+    OMX_U32 nBLayerCountMax;
+    OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE ePattern;
+    OMX_U32 nPLayerCountActual;
+    OMX_U32 nBLayerCountActual;
+    OMX_BOOL bBitrateRatiosSpecified;
+    OMX_U32 nBitrateRatios[OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS];
+} OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE;
+
+/**
+ * Android specific config for changing the temporal-layer count or
+ * bitrate-distribution at run-time.
+ *
+ *  nSize                      : Size of the structure in bytes
+ *  nVersion                   : OMX specification version information
+ *  nPortIndex                 : Port that this structure applies to (output port for encoders)
+ *  ePattern                   : Layering pattern.
+ *  nPLayerCountActual         : Number of temporal layers to be coded with non-B frames.
+ *                               (same OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE limits apply.)
+ *  nBLayerCountActual         : Number of temporal layers to be coded with B frames.
+ *                               (same OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE limits apply.)
+ *  bBitrateRatiosSpecified    : Flag to indicate if layer-wise bitrate
+ *                               distribution is specified.
+ *  nBitrateRatios             : Bitrate ratio (100 based, Q16 values) per layer (0 is base layer).
+ *                               Honored if bBitrateRatiosSpecified is set.
+ *                               (same OMX_VIDEO_PARAM_ANDROID_TEMPORALLAYERINGTYPE limits apply.)
+ */
+typedef struct OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE {
+    OMX_U32 nSize;
+    OMX_VERSIONTYPE nVersion;
+    OMX_U32 nPortIndex;
+    OMX_VIDEO_ANDROID_TEMPORALLAYERINGPATTERNTYPE ePattern;
+    OMX_U32 nPLayerCountActual;
+    OMX_U32 nBLayerCountActual;
+    OMX_BOOL bBitrateRatiosSpecified;
+    OMX_U32 nBitrateRatios[OMX_VIDEO_ANDROID_MAXTEMPORALLAYERS];
+} OMX_VIDEO_CONFIG_ANDROID_TEMPORALLAYERINGTYPE;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* OMX_VideoExt_h */
+/* File EOF */
