diff options
55 files changed, 4380 insertions, 106 deletions
diff --git a/common/recipes-multimedia/gstreamer/gst-plugins-bad_0.10.23.bbappend b/common/recipes-multimedia/gstreamer/gst-plugins-bad_0.10.23.bbappend index 1696313..6b7f1d8 100644 --- a/common/recipes-multimedia/gstreamer/gst-plugins-bad_0.10.23.bbappend +++ b/common/recipes-multimedia/gstreamer/gst-plugins-bad_0.10.23.bbappend @@ -5,26 +5,5 @@ EXTRA_OECONF += "--with-plugins=h264parse,asfmux,videoparsers" TARGET_CFLAGS += "-D_GNU_SOURCE" FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" -# For armadillo -SRCREV_armadillo800eva = "6c0a11cb57d4425f6d721a6756c5af4d9dd269e5" -SRC_URI_armadillo800eva = " \ - git://github.com/matsu/gst-plugins-bad.git \ - file://0001-Setup-MERAM-for-A1.patch \ -" - -S_armadillo800eva = "${WORKDIR}/git/" -DEPENDS_append_armadillo800eva = " directfb libuiomux libshvio" -EXTRA_OECONF_armadillo800eva = "${@'${EXTRA_OECONF}'.replace('--disable-directfb', '--enable-directfb')}" - -EXTRA_OECONF_append_armadillo800eva = " \ - --disable-librfb --enable-introspection=no \ - --disable-nls --disable-static --disable-gsettings \ -" - -do_configure_armadillo800eva() { - (cd ${S}; sh autogen.sh --noconfigure) - oe_runconf -} - FILES_${PN} += "${bindir}" require gst-plugins-private-libs.inc diff --git a/common/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.2.3.bbappend b/common/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.2.3.bbappend index 2f46ba3..ae95283 100644 --- a/common/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.2.3.bbappend +++ b/common/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.2.3.bbappend @@ -1,5 +1,5 @@ PACKAGECONFIG ??= " \ - ${@base_contains('DISTRO_FEATURES', 'x11', 'x11', '', d)} \ - ${@base_contains('DISTRO_FEATURES', 'alsa', 'alsa', '', d)} \ + ${@bb.utils.contains('DISTRO_FEATURES', 'x11', 'x11', '', d)} \ + ${@bb.utils.contains('DISTRO_FEATURES', 'alsa', 'alsa', '', d)} \ ivorbis ogg theora vorbis \ " diff --git a/common/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.2.3.bbappend b/common/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.2.3.bbappend index 910b031..c67449f 100644 --- a/common/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.2.3.bbappend +++ b/common/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.2.3.bbappend @@ -1,5 +1,5 @@ PACKAGECONFIG ??= " \ - ${@base_contains('DISTRO_FEATURES', 'x11', 'x11', '', d)} \ - ${@base_contains('DISTRO_FEATURES', 'pulseaudio', 'pulseaudio', '', d)} \ + ${@bb.utils.contains('DISTRO_FEATURES', 'x11', 'x11', '', d)} \ + ${@bb.utils.contains('DISTRO_FEATURES', 'pulseaudio', 'pulseaudio', '', d)} \ cairo flac gdk-pixbuf jpeg libpng soup speex taglib \ " diff --git a/common/recipes-multimedia/omxil-sh/omxil-sh_git.bb b/common/recipes-multimedia/omxil-sh/omxil-sh_git.bb index e65072b..96124f5 100644 --- a/common/recipes-multimedia/omxil-sh/omxil-sh_git.bb +++ b/common/recipes-multimedia/omxil-sh/omxil-sh_git.bb @@ -23,7 +23,7 @@ SRCREV_armadillo800eva = "bd43cfba750773cd323fb546f279e76b37c6d713" SRC_URI_append_armadillo800eva = " file://vcp1-library-change.patch" CHECK_OMXIL_SH_MW = "${USE_RENESAS_MW_VCP1}" CHECK_OMXIL_SH_MW += "${USE_RENESAS_MW_VPU5}" -DEPENDS_append_armadillo800eva = ' ${@base_contains("CHECK_OMXIL_SH_MW", "1", "vcp1", "", d)}' +DEPENDS_append_armadillo800eva = ' ${@bb.utils.contains("CHECK_OMXIL_SH_MW", "1", "vcp1", "", d)}' inherit autotools pkgconfig diff --git a/conf/layer.conf b/conf/layer.conf index 318293a..429a56b 100644 --- a/conf/layer.conf +++ b/conf/layer.conf @@ -9,7 +9,4 @@ BBFILE_COLLECTIONS += "renesas" BBFILE_PATTERN_renesas := "^${LAYERDIR}/" BBFILE_PRIORITY_renesas = "5" -PREFERRED_VERSION_mesa = "12.0.1" -PREFERRED_VERSION_gnutls = "3.3.%" -PREFERRED_VERSION_libtasn1 = "4.5" PREFERRED_VERSION_libnl = "3.2.25" diff --git a/meta-rcar-gen2/README.proprietary b/meta-rcar-gen2/README.proprietary index 0da8afe..4cbcfad 100644 --- a/meta-rcar-gen2/README.proprietary +++ b/meta-rcar-gen2/README.proprietary @@ -44,9 +44,9 @@ II/ Build with or without GLES PREFERRED_PROVIDER_virtual/libgles2 = "gles-user-module" PREFERRED_PROVIDER_virtual/egl = "libegl" PREFERRED_PROVIDER_virtual/libgl = "" - PREFERRED_PROVIDER_virtual/mesa = "" + PREFERRED_PROVIDER_virtual/mesa = "mesa" PREFERRED_PROVIDER_libgbm = "libgbm" - PREFERRED_PROVIDER_libgbm-dev = "libgbm" + PREFERRED_RPROVIDER_libgbm-dev = "libgbm" NOTE: The r8a7790 uses rgx, r8a7791, r8a7793 and r8a7794 uses sgx. If you want to use rgx, please set to 'rgx' instead of 'sgx'. diff --git a/meta-rcar-gen2/include/omx-components-control.inc b/meta-rcar-gen2/include/omx-components-control.inc index 7848262..f8977fc 100644 --- a/meta-rcar-gen2/include/omx-components-control.inc +++ b/meta-rcar-gen2/include/omx-components-control.inc @@ -66,7 +66,7 @@ USE_AUDIO_COMMON = "${@'1' if '1' in '${AUDIO_ENCODER_ARRAY}' or '1' in '${AUDIO # Please add new encoder config into list when have new encoder (e.g. as RESERVE_ENCODER_CONF) VIDEO_ENCODER_ARRAY = "${USE_H264AVC_ENCODER}" #VIDEO_ENCODER_ARRAY += "${RESERVE_ENCODER_CONF}" -USE_VIDEO_COMMON_ENCODER = '${@base_contains("VIDEO_ENCODER_ARRAY", "1", "1", "0", d)}' +USE_VIDEO_COMMON_ENCODER = '${@bb.utils.contains("VIDEO_ENCODER_ARRAY", "1", "1", "0", d)}' # Audio codec config ARMAACP2_MDW_DECODER = '${@base_conditional("USE_AACP2_DECODER", "1", "1", "${USE_ARMAACP2_MDW_DECODER}", d)}' diff --git a/meta-rcar-gen2/recipes-bsp/bootfiles/files/uEnv-ota.txt b/meta-rcar-gen2/recipes-bsp/bootfiles/files/uEnv-ota.txt new file mode 100644 index 0000000..9def764 --- /dev/null +++ b/meta-rcar-gen2/recipes-bsp/bootfiles/files/uEnv-ota.txt @@ -0,0 +1,18 @@ +bootkaddr=0x40007fc0 +bootiaddr=0x50000000 + +bootargs_console=console=ttySC6,38400 ignore_loglevel +bootargs_video=vmalloc=384M video=HDMI-A-1:1024x768-32@60 +bootargs_extra=rw rootfstype=ext4 rootwait rootdelay=2 + +bootargs_root=ostree_root=/dev/mmcblk0p2 root=/dev/ram0 ramdisk_size=16384 + +bootmmc=1:2 + +booteload_sd=ext4load mmc ${bootmmc} ${bootkaddr} boot/loader/uEnv.txt; env import -t ${bootkaddr} ${filesize} + +bootkload_sd=ext4load mmc ${bootmmc} ${bootkaddr} boot/${kernel_image} +bootiload_sd=ext4load mmc ${bootmmc} ${bootiaddr} boot/${ramdisk_image} + +bootcmd=run booteload_sd; setenv bootargs ${bootargs} ${bootargs_console} ${bootargs_video} ${bootargs_root} ${bootargs_extra}; run bootkload_sd; run bootiload_sd; bootm ${bootkaddr} ${bootiaddr} + diff --git a/meta-rcar-gen2/recipes-bsp/bootfiles/porter-bootfiles.bb b/meta-rcar-gen2/recipes-bsp/bootfiles/porter-bootfiles.bb new file mode 100644 index 0000000..2c14a88 --- /dev/null +++ b/meta-rcar-gen2/recipes-bsp/bootfiles/porter-bootfiles.bb @@ -0,0 +1,25 @@ +DESCRIPTION = "Boot files (bootscripts etc.) for Renesas Porter board" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420" + +inherit deploy + +COMPATIBLE_MACHINE = "porter" + +S = "${WORKDIR}" + +SRC_URI_append_sota = "file://uEnv-ota.txt" + +do_deploy() { + install -d ${DEPLOYDIR}/${PN} +} + +do_deploy_append_sota() { + install -m 0755 ${WORKDIR}/uEnv-ota.txt ${DEPLOYDIR}/${PN}/uEnv.txt +} + +addtask deploy before do_package after do_install +do_deploy[dirs] += "${DEPLOYDIR}/${PN}" + +PACKAGE_ARCH = "${MACHINE_ARCH}" + diff --git a/meta-rcar-gen2/recipes-bsp/u-boot/u-boot/0004-uboot-porter-board-support.patch b/meta-rcar-gen2/recipes-bsp/u-boot/u-boot/0004-uboot-porter-board-support.patch index f83620b..0c48b09 100644 --- a/meta-rcar-gen2/recipes-bsp/u-boot/u-boot/0004-uboot-porter-board-support.patch +++ b/meta-rcar-gen2/recipes-bsp/u-boot/u-boot/0004-uboot-porter-board-support.patch @@ -403,9 +403,9 @@ index 0000000..e6ded08 + u8 val; + + i2c_init(CONFIG_SYS_I2C_SPEED, 0); -+ i2c_read(0x58, 0x13, 1, &val, 1); ++ i2c_read(0x5a, 0x13, 1, &val, 1); + val |= 0x02; -+ i2c_write(0x58, 0x13, 1, &val, 1); ++ i2c_write(0x5a, 0x13, 1, &val, 1); +} + +enum { @@ -3071,9 +3071,9 @@ index 0000000..0d68248 + +#define CONFIG_SYS_LONGHELP +#define CONFIG_SYS_PROMPT "=> " -+#define CONFIG_SYS_CBSIZE 256 -+#define CONFIG_SYS_PBSIZE 256 -+#define CONFIG_SYS_MAXARGS 16 ++#define CONFIG_SYS_CBSIZE 512 ++#define CONFIG_SYS_PBSIZE 512 ++#define CONFIG_SYS_MAXARGS 32 +#define CONFIG_SYS_BARGSIZE 512 +#define CONFIG_SYS_BAUDRATE_TABLE { 38400, 115200 } + diff --git a/meta-rcar-gen2/recipes-graphics/gles-module/gles-user-module.bb b/meta-rcar-gen2/recipes-graphics/gles-module/gles-user-module.bb index 8a72b12..37e8052 100644 --- a/meta-rcar-gen2/recipes-graphics/gles-module/gles-user-module.bb +++ b/meta-rcar-gen2/recipes-graphics/gles-module/gles-user-module.bb @@ -26,23 +26,23 @@ OPENGLES3 ?= "0" SRC_URI_r8a7790 = '${@base_conditional( "OPENGLES3", "1", \ "file://r8a7790_linux_rgx_binaries_gles3.tar.bz2", \ "file://r8a7790_linux_rgx_binaries_gles2.tar.bz2", d )}' -SRC_URI_append_r8a7790 = " ${@base_contains("DISTRO_FEATURES", "wayland", " \ +SRC_URI_append_r8a7790 = " ${@bb.utils.contains("DISTRO_FEATURES", "wayland", " \ file://EGL_headers_for_wayland.patch \ file://change-shell.patch \ ", "", d)}" SRC_URI_r8a7791 = "file://r8a7791_linux_sgx_binaries_gles2.tar.bz2" -SRC_URI_append_r8a7791 = " ${@base_contains("DISTRO_FEATURES", "wayland", " \ +SRC_URI_append_r8a7791 = " ${@bb.utils.contains("DISTRO_FEATURES", "wayland", " \ file://EGL_headers_for_wayland.patch \ ", "", d)}" SRC_URI_r8a7793 = "file://r8a7791_linux_sgx_binaries_gles2.tar.bz2" -SRC_URI_append_r8a7793 = " ${@base_contains("DISTRO_FEATURES", "wayland", " \ +SRC_URI_append_r8a7793 = " ${@bb.utils.contains("DISTRO_FEATURES", "wayland", " \ file://EGL_headers_for_wayland.patch \ ", "", d)}" SRC_URI_r8a7794 = "file://r8a7794_linux_sgx_binaries_gles2.tar.bz2" -SRC_URI_append_r8a7794 = " ${@base_contains("DISTRO_FEATURES", "wayland", " \ +SRC_URI_append_r8a7794 = " ${@bb.utils.contains("DISTRO_FEATURES", "wayland", " \ file://EGL_headers_for_wayland.patch \ ", "", d)}" @@ -100,7 +100,7 @@ FILES_${PN}-dev = " \ " PROVIDES = "virtual/libgles2" -PROVIDES_append = "${@base_contains("DISTRO_FEATURES", "wayland", "", " virtual/egl", d)}" +PROVIDES_append = "${@bb.utils.contains("DISTRO_FEATURES", "wayland", "", " virtual/egl", d)}" RPROVIDES_${PN} += "${GLES}-user-module libgles2-mesa libgles2-mesa-dev libgles2 libgles2-dev" INSANE_SKIP_${PN} += "ldflags already-stripped" INSANE_SKIP_${PN}-dev += "ldflags" diff --git a/meta-rcar-gen2/recipes-graphics/images/core-image-renesas-base.inc b/meta-rcar-gen2/recipes-graphics/images/core-image-renesas-base.inc index bea1510..ee20a28 100644 --- a/meta-rcar-gen2/recipes-graphics/images/core-image-renesas-base.inc +++ b/meta-rcar-gen2/recipes-graphics/images/core-image-renesas-base.inc @@ -27,18 +27,18 @@ IMAGE_INSTALL_append_rcar-gen2 = '${@base_conditional("USE_GLES", "1", \ "gles-kernel-module gles-user-module", "", d)}' # pkg groups for multimedia -IMAGE_INSTALL_append_rcar-gen2 = ' ${@base_contains("USE_MULTIMEDIA", "1", " \ +IMAGE_INSTALL_append_rcar-gen2 = ' ${@bb.utils.contains("USE_MULTIMEDIA", "1", " \ packagegroup-rcar-gen2-multimedia \ ", "", d)}' # pkg groups for multimedia test program -IMAGE_INSTALL_append_rcar-gen2 = ' ${@base_contains("USE_MULTIMEDIA_TEST", "1", " \ +IMAGE_INSTALL_append_rcar-gen2 = ' ${@bb.utils.contains("USE_MULTIMEDIA_TEST", "1", " \ packagegroup-rcar-gen2-multimedia-tp \ ", "", d)}' # pkg groups for dtv -IMAGE_INSTALL_append_rcar-gen2 = ' ${@base_contains("USE_DTV", "1", " \ +IMAGE_INSTALL_append_rcar-gen2 = ' ${@bb.utils.contains("USE_DTV", "1", " \ packagegroup-rcar-gen2-dtv \ ", "", d)}' # pkg groups for graphic test program -IMAGE_INSTALL_append_rcar-gen2 = ' ${@base_contains("USE_GLES_TEST", "1", " \ +IMAGE_INSTALL_append_rcar-gen2 = ' ${@bb.utils.contains("USE_GLES_TEST", "1", " \ gles-test-module \ ", "", d)}' diff --git a/meta-rcar-gen2/recipes-graphics/mesa/mesa-wayland.inc b/meta-rcar-gen2/recipes-graphics/mesa/mesa-wayland.inc index 572c1a7..be051ca 100644 --- a/meta-rcar-gen2/recipes-graphics/mesa/mesa-wayland.inc +++ b/meta-rcar-gen2/recipes-graphics/mesa/mesa-wayland.inc @@ -2,7 +2,7 @@ PACKAGECONFIG[gles] = "--enable-gles1 --disable-gles2" PACKAGECONFIG[egl] = "--enable-egl --with-egl-platforms=wayland" -FILESEXTRAPATHS_prepend := "${THISDIR}/mesa_10.6.3/:" +FILESEXTRAPATHS_prepend := "${THISDIR}/mesa/:" SRC_URI += "file://0001-dri2-Fix-fstat-s_ISHCR-implict-declaration-build-err.patch" # Disable the gbm modules of mesa diff --git a/meta-rcar-gen2/recipes-graphics/mesa/mesa_10.6.3/0001-dri2-Fix-fstat-s_ISHCR-implict-declaration-build-err.patch b/meta-rcar-gen2/recipes-graphics/mesa/mesa/0001-dri2-Fix-fstat-s_ISHCR-implict-declaration-build-err.patch index 909e0d0..909e0d0 100644 --- a/meta-rcar-gen2/recipes-graphics/mesa/mesa_10.6.3/0001-dri2-Fix-fstat-s_ISHCR-implict-declaration-build-err.patch +++ b/meta-rcar-gen2/recipes-graphics/mesa/mesa/0001-dri2-Fix-fstat-s_ISHCR-implict-declaration-build-err.patch diff --git a/meta-rcar-gen2/recipes-graphics/wayland/libegl.bb b/meta-rcar-gen2/recipes-graphics/wayland/libegl.bb index 5fffe16..b53b2a3 100644 --- a/meta-rcar-gen2/recipes-graphics/wayland/libegl.bb +++ b/meta-rcar-gen2/recipes-graphics/wayland/libegl.bb @@ -4,8 +4,8 @@ LIC_FILES_CHKSUM = "file://egl.c;beginline=5;endline=15;md5=3677623633a6e459b1f6 COMPATIBLE_MACHINE = "(r8a7790|r8a7791|r8a7793|r8a7794)" -RPROVIDES_${PN} = "${@base_contains("DISTRO_FEATURES", "wayland", "libEGL.so", "", d)}" -PROVIDES = "${@base_contains("DISTRO_FEATURES", "wayland", "virtual/egl", "", d)}" +RPROVIDES_${PN} = "${@bb.utils.contains("DISTRO_FEATURES", "wayland", "libEGL.so", "", d)}" +PROVIDES = "${@bb.utils.contains("DISTRO_FEATURES", "wayland", "virtual/egl", "", d)}" SRCREV = "7b09cce97e8658ba927e71f1af43360c4cc392b7" SRC_URI = "git://github.com/thayama/libegl;protocol=git;branch=master \ file://0001-libegl-Remove-duplicate-header-files-of-gles-user-mo.patch" diff --git a/meta-rcar-gen2/recipes-graphics/wayland/libgbm.bb b/meta-rcar-gen2/recipes-graphics/wayland/libgbm.bb index de66361..3817fb1 100644 --- a/meta-rcar-gen2/recipes-graphics/wayland/libgbm.bb +++ b/meta-rcar-gen2/recipes-graphics/wayland/libgbm.bb @@ -7,6 +7,10 @@ LIC_FILES_CHKSUM = "file://gbm.c;beginline=4;endline=22;md5=5cdaac262c876e98e477 SRCREV = "c4ee70a7202dc81eaa45a73535e82cee98db2a0d" SRC_URI = "git://github.com/thayama/libgbm;protocol=git;branch=master" +SRC_URI_append = " \ + file://0001-Add-gbm_bo_get_fd-function.patch \ +" + S = "${WORKDIR}/git" COMPATIBLE_MACHINE = "(r8a7790|r8a7791|r8a7793|r8a7794)" diff --git a/meta-rcar-gen2/recipes-graphics/wayland/libgbm/0001-Add-gbm_bo_get_fd-function.patch b/meta-rcar-gen2/recipes-graphics/wayland/libgbm/0001-Add-gbm_bo_get_fd-function.patch new file mode 100644 index 0000000..e688cde --- /dev/null +++ b/meta-rcar-gen2/recipes-graphics/wayland/libgbm/0001-Add-gbm_bo_get_fd-function.patch @@ -0,0 +1,90 @@ +From e6d4594481a2c7d9625d1f4abf898cd461c30c42 Mon Sep 17 00:00:00 2001 +From: Grigory Kletsko <grigory.kletsko@cogentembedded.com> +Date: Wed, 2 Nov 2016 16:17:16 +0300 +Subject: [PATCH] Add gbm_bo_get_fd() function + +--- + backend_kms.c | 8 ++++++++ + gbm.c | 15 +++++++++++++++ + gbm.h | 3 +++ + gbmint.h | 1 + + 4 files changed, 27 insertions(+) + +diff --git a/backend_kms.c b/backend_kms.c +index cfee3b0..3fc1d66 100644 +--- a/backend_kms.c ++++ b/backend_kms.c +@@ -339,6 +339,13 @@ static int gbm_kms_surface_has_free_buffers(struct gbm_surface *_surface) + return ((!surface->bo[0]->locked) || (!surface->bo[1]->locked)); + } + ++static int gbm_kms_bo_get_fd(struct gbm_bo *_bo) ++{ ++ struct gbm_kms_bo *bo = (struct gbm_kms_bo*)_bo; ++ ++ return bo->fd; ++} ++ + struct gbm_device kms_gbm_device = { + .name = "kms", + +@@ -349,6 +356,7 @@ struct gbm_device kms_gbm_device = { + .bo_import = gbm_kms_bo_import, + .bo_write = gbm_kms_bo_write, + .bo_destroy = gbm_kms_bo_destroy, ++ .bo_get_fd = gbm_kms_bo_get_fd, + + .surface_create = gbm_kms_surface_create, + .surface_lock_front_buffer = gbm_kms_surface_lock_front_buffer, +diff --git a/gbm.c b/gbm.c +index c58576d..458fac0 100644 +--- a/gbm.c ++++ b/gbm.c +@@ -470,3 +470,18 @@ gbm_surface_has_free_buffers(struct gbm_surface *surf) + { + return surf->gbm->surface_has_free_buffers(surf); + } ++ ++/** Get a DMA-BUF file descriptor for the buffer object ++ * ++ * This function creates a DMA-BUF (also known as PRIME) file descriptor ++ * handle for the buffer object. Eeach call to gbm_bo_get_fd() returns a new ++ * file descriptor and the caller is responsible for closing the file ++ * descriptor. ++ * \param bo The buffer object ++ * \return Returns a file descriptor referring to the underlying buffer ++ */ ++GBM_EXPORT int ++gbm_bo_get_fd(struct gbm_bo *bo) ++{ ++ return bo->gbm->bo_get_fd(bo); ++} +diff --git a/gbm.h b/gbm.h +index 9d2a030..ad92935 100644 +--- a/gbm.h ++++ b/gbm.h +@@ -285,6 +285,9 @@ gbm_surface_has_free_buffers(struct gbm_surface *surface); + void + gbm_surface_destroy(struct gbm_surface *surface); + ++int ++gbm_bo_get_fd(struct gbm_bo *bo); ++ + #ifdef __cplusplus + } + #endif +diff --git a/gbmint.h b/gbmint.h +index a467bea..70a8d4a 100644 +--- a/gbmint.h ++++ b/gbmint.h +@@ -70,6 +70,7 @@ struct gbm_device { + void *buffer, uint32_t usage); + int (*bo_write)(struct gbm_bo *bo, const void *buf, size_t data); + void (*bo_destroy)(struct gbm_bo *bo); ++ int (*bo_get_fd)(struct gbm_bo *_bo); + + struct gbm_surface *(*surface_create)(struct gbm_device *gbm, + uint32_t width, uint32_t height, +-- +2.7.4 + diff --git a/meta-rcar-gen2/recipes-kernel/fdpm-module/fdpm-kernel-module.bb b/meta-rcar-gen2/recipes-kernel/fdpm-module/fdpm-kernel-module.bb index 73e7615..1886730 100644 --- a/meta-rcar-gen2/recipes-kernel/fdpm-module/fdpm-kernel-module.bb +++ b/meta-rcar-gen2/recipes-kernel/fdpm-module/fdpm-kernel-module.bb @@ -1,6 +1,6 @@ require ../../include/rcar-gen2-modules-common.inc -LICENSE = "GPLv2&MIT" +LICENSE = "GPLv2 & MIT" LIC_FILES_CHKSUM = "file://drv/GPL-COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \ file://drv/MIT-COPYING;md5=fea016ce2bdf2ec10080f69e9381d378" diff --git a/meta-rcar-gen2/recipes-kernel/gles-module/gles-kernel-module.bb b/meta-rcar-gen2/recipes-kernel/gles-module/gles-kernel-module.bb index 5b47340..e3fea90 100644 --- a/meta-rcar-gen2/recipes-kernel/gles-module/gles-kernel-module.bb +++ b/meta-rcar-gen2/recipes-kernel/gles-module/gles-kernel-module.bb @@ -1,5 +1,5 @@ DESCRIPTION = "RGX/SGX kernel module" -LICENSE = "GPLv2&MIT" +LICENSE = "GPLv2 & MIT" LIC_FILES_CHKSUM = "file://GPL-COPYING;md5=60422928ba677faaa13d6ab5f5baaa1e \ file://MIT-COPYING;md5=8c2810fa6bfdc5ae5c15a0c1ade34054" DEPENDS = "linux-renesas" @@ -29,8 +29,8 @@ S_r8a7794 = "${WORKDIR}/eurasia_km" KERNEL_SRC_PATH_r8a7794 = "eurasiacon/build/linux2/r8a7794_linux/" TARGET_PATH_r8a7794 = "eurasia_km/eurasiacon/binary2_r8a7794_linux_release/target/kbuild" -GLES = "${@base_contains('MACHINE_FEATURES', 'rgx', 'rgx', \ - base_contains('MACHINE_FEATURES', 'sgx', 'sgx', '', d), d)}" +GLES = "${@bb.utils.contains('MACHINE_FEATURES', 'rgx', 'rgx', \ + bb.utils.contains('MACHINE_FEATURES', 'sgx', 'sgx', '', d), d)}" RPROVIDES_${PN} += "${GLES}-kernel-module" RPROVIDES_${PN} += "kernel-module-bc-example kernel-module-pvrsrvkm kernel-module-dc-linuxfb" @@ -40,7 +40,6 @@ INHIBIT_PACKAGE_DEBUG_SPLIT = "1" do_patch[noexec] = "1" do_configure[noexec] = "1" -do_populate_lic[noexec] = "1" export BUILDDIR = "${STAGING_INCDIR}/.." export LIBSHARED = "${STAGING_LIBDIR}" diff --git a/meta-rcar-gen2/recipes-kernel/linux-libc-headers/linux-libc-headers_3.10.bb b/meta-rcar-gen2/recipes-kernel/linux-libc-headers/linux-libc-headers_3.10.bb index 3e18e9e..374bee0 100644 --- a/meta-rcar-gen2/recipes-kernel/linux-libc-headers/linux-libc-headers_3.10.bb +++ b/meta-rcar-gen2/recipes-kernel/linux-libc-headers/linux-libc-headers_3.10.bb @@ -8,8 +8,8 @@ PV_append = "+git${SRCREV}" FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" RENESAS_BACKPORTS_URL="git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas-backport.git" -SRCREV = "b8ca8c397343f4233f9f68fc3a5bf8e1c9b88251" -SRC_URI = "${RENESAS_BACKPORTS_URL};protocol=git;branch=bsp/v3.10.31-ltsi/rcar-gen2-1.9.2 \ +SRCREV = "165e12ce2d7839e755debbec78dfa43b54345275" +SRC_URI = "${RENESAS_BACKPORTS_URL};protocol=git;branch=bsp/v3.10.31-ltsi/rcar-gen2-1.9.7 \ file://scripts-Makefile.headersinst-install-headers-from-sc.patch \ file://0001-kernel-add-support-for-gcc-5.patch \ file://0001-kernel-add-support-for-gcc-6.patch \ diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-ASoC-ak4642-Replace-mdelay-function-to-msleep.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-ASoC-ak4642-Replace-mdelay-function-to-msleep.patch new file mode 100644 index 0000000..7bfff9a --- /dev/null +++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0001-ASoC-ak4642-Replace-mdelay-function-to-msleep.patch @@ -0,0 +1,29 @@ +From 21b85faf93b8028cfa477279354bedab93dcea04 Mon Sep 17 00:00:00 2001 +From: Harunobu Kurokawa <harunobu.kurokawa.dn@renesas.com> +Date: Wed, 21 Dec 2016 11:27:34 +0900 +Subject: [PATCH] ASoC: ak4642: Replace mdelay function to msleep + +Replace mdelay to msleep to avoid busy loop on ak4642_lout_event(). +Otherwise, sometimes playback doesn't work correctly when pulseaudio was used. + +Signed-off-by: Harunobu Kurokawa <harunobu.kurokawa.dn@renesas.com> +--- + sound/soc/codecs/ak4642.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c +index 40500cd..0205ae1 100644 +--- a/sound/soc/codecs/ak4642.c ++++ b/sound/soc/codecs/ak4642.c +@@ -186,7 +186,7 @@ static int ak4642_lout_event(struct snd_soc_dapm_widget *w, + break; + case SND_SOC_DAPM_POST_PMU: /* after widget power up */ + /* Power save mode OFF */ +- mdelay(popup_wait); ++ msleep(popup_wait); + snd_soc_update_bits(codec, SG_SL2, LOPS, 0); + break; + case SND_SOC_DAPM_PRE_PMD: /* before widget power down */ +-- +2.9.2 + diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0002-silk-reference-Add-DRM_RCAR_DU_CONNECT_VSP-configura.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0002-silk-reference-Add-DRM_RCAR_DU_CONNECT_VSP-configura.patch new file mode 100644 index 0000000..6eff1c3 --- /dev/null +++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0002-silk-reference-Add-DRM_RCAR_DU_CONNECT_VSP-configura.patch @@ -0,0 +1,74 @@ +From 1dd26e7ff4bd7f9f5c4926ea3e10f0c56df04cc2 Mon Sep 17 00:00:00 2001 +From: Yannick Gicquel <yannick.gicquel@iot.bzh> +Date: Wed, 7 Sep 2016 14:38:49 +0200 +Subject: [PATCH] silk-reference: Add DRM_RCAR_DU_CONNECT_VSP configuration + +Signed-off-by: Yannick Gicquel <yannick.gicquel@iot.bzh> +--- + arch/arm/mach-shmobile/board-silk-reference.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/arch/arm/mach-shmobile/board-silk-reference.c b/arch/arm/mach-shmobile/board-silk-reference.c +index d4c64fa..9195c0f 100644 +--- a/arch/arm/mach-shmobile/board-silk-reference.c ++++ b/arch/arm/mach-shmobile/board-silk-reference.c +@@ -31,7 +31,8 @@ + #include <linux/platform_data/camera-rcar.h> + #include <linux/platform_data/rcar-du.h> + #include <linux/platform_data/usb-rcar-gen2-phy.h> +-#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1) ++#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1) && \ ++!defined(CONFIG_DRM_RCAR_DU_CONNECT_VSP) + #include <linux/platform_data/vsp1.h> + #endif + #include <linux/serial_sci.h> +@@ -91,10 +92,16 @@ static struct rcar_du_crtc_data silk_du_crtcs[] = { + { + .exclk = 148500000, + .init_conn_type = DRM_MODE_CONNECTOR_HDMIA, ++#ifdef CONFIG_DRM_RCAR_DU_CONNECT_VSP ++ .vsp = CONFIG_DRM_RCAR_DU0_USE_VSPDU_CH, ++#endif + }, + { + .exclk = 74250000, + .init_conn_type = DRM_MODE_CONNECTOR_VGA, ++#ifdef CONFIG_DRM_RCAR_DU_CONNECT_VSP ++ .vsp = CONFIG_DRM_RCAR_DU1_USE_VSPDU_CH, ++#endif + }, + }; + +@@ -250,7 +257,8 @@ static const struct clk_name clk_names[] __initconst = { + { "dvc1", "dvc.1", "rcar_sound" }, + { "vin0", NULL, "r8a7794-vin.0" }, + { "vsps", NULL, NULL }, +-#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1) ++#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1) && \ ++!defined(CONFIG_DRM_RCAR_DU_CONNECT_VSP) + { "vsp1-du0", NULL, "vsp1.2" }, + #else + { "vsp1-du0", NULL, NULL }, +@@ -821,7 +829,8 @@ static void __init silk_add_camera0_device(void) + } + + /* VSP1 */ +-#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1) ++#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1) && \ ++!defined(CONFIG_DRM_RCAR_DU_CONNECT_VSP) + static const struct vsp1_platform_data silk_vsps_pdata __initconst = { + .features = 0, + .rpf_count = 5, +@@ -970,7 +979,8 @@ static void __init silk_add_standard_devices(void) + silk_add_usb1_device(); + silk_add_rsnd_device(); + silk_add_camera0_device(); +-#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1) ++#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1) && \ ++!defined(CONFIG_DRM_RCAR_DU_CONNECT_VSP) + silk_add_vsp1_devices(); + #endif + silk_add_msiof_device(spi_bus, ARRAY_SIZE(spi_bus)); +-- +1.9.1 + diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0008-Porter-board-support.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0008-Porter-board-support.patch index 13fc68b..e452f0e 100644 --- a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0008-Porter-board-support.patch +++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0008-Porter-board-support.patch @@ -1322,7 +1322,7 @@ index 0000000..d481ecd + +/* POWER IC */ +static struct i2c_board_info poweric_i2c[] = { -+ { I2C_BOARD_INFO("da9063", 0x58), }, ++ { I2C_BOARD_INFO("da9063", 0x5a), }, +}; + +static void porter_restart(char mode, const char *cmd) diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0009-porter-reference-Add-DRM_RCAR_DU_CONNECT_VSP-configu.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0009-porter-reference-Add-DRM_RCAR_DU_CONNECT_VSP-configu.patch new file mode 100644 index 0000000..b712a19 --- /dev/null +++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/0009-porter-reference-Add-DRM_RCAR_DU_CONNECT_VSP-configu.patch @@ -0,0 +1,74 @@ +From 0a907ffb0598971a603eb0a4117cf251974c33b8 Mon Sep 17 00:00:00 2001 +From: Yannick Gicquel <yannick.gicquel@iot.bzh> +Date: Wed, 7 Sep 2016 13:59:40 +0200 +Subject: [PATCH] porter-reference: Add DRM_RCAR_DU_CONNECT_VSP configuration + +Signed-off-by: Yannick Gicquel <yannick.gicquel@iot.bzh> +--- + arch/arm/mach-shmobile/board-porter-reference.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/arch/arm/mach-shmobile/board-porter-reference.c b/arch/arm/mach-shmobile/board-porter-reference.c +index ae06151..75513cb 100644 +--- a/arch/arm/mach-shmobile/board-porter-reference.c ++++ b/arch/arm/mach-shmobile/board-porter-reference.c +@@ -30,7 +30,8 @@ + #include <linux/platform_data/camera-rcar.h> + #include <linux/platform_data/rcar-du.h> + #include <linux/platform_data/usb-rcar-gen2-phy.h> +-#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1) ++#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1) && \ ++!defined(CONFIG_DRM_RCAR_DU_CONNECT_VSP) + #include <linux/platform_data/vsp1.h> + #endif + #include <linux/serial_sci.h> +@@ -86,10 +87,16 @@ static struct rcar_du_crtc_data porter_du_crtcs[] = { + { + .exclk = 0, /* NoP */ + .init_conn_type = DRM_MODE_CONNECTOR_LVDS, ++#ifdef CONFIG_DRM_RCAR_DU_CONNECT_VSP ++ .vsp = CONFIG_DRM_RCAR_DU0_USE_VSPDU_CH, ++#endif + }, + { + .exclk = 0, /* NoP */ + .init_conn_type = DRM_MODE_CONNECTOR_HDMIA, ++#ifdef CONFIG_DRM_RCAR_DU_CONNECT_VSP ++ .vsp = CONFIG_DRM_RCAR_DU1_USE_VSPDU_CH, ++#endif + }, + }; + +@@ -139,7 +146,8 @@ static const struct clk_name clk_names[] __initconst = { + { "hsusb", NULL, "usb_phy_rcar_gen2" }, + { "vin0", NULL, "r8a7791-vin.0" }, + { "vsps", NULL, NULL }, +-#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1) ++#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1) && \ ++!defined(CONFIG_DRM_RCAR_DU_CONNECT_VSP) + { "vsp1-du0", NULL, "vsp1.2" }, + { "vsp1-du1", NULL, "vsp1.3" }, + #else +@@ -661,7 +669,8 @@ static void __init porter_add_camera0_device(void) + } + + /* VSP1 */ +-#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1) ++#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1) && \ ++!defined(CONFIG_DRM_RCAR_DU_CONNECT_VSP) + static const struct vsp1_platform_data porter_vsps_pdata __initconst = { + .features = 0, + .rpf_count = 5, +@@ -850,7 +859,8 @@ static void __init porter_add_standard_devices(void) + porter_add_du_device(); + porter_add_usb_devices(); + porter_add_camera0_device(); +-#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1) ++#if IS_ENABLED(CONFIG_VIDEO_RENESAS_VSP1) && \ ++!defined(CONFIG_DRM_RCAR_DU_CONNECT_VSP) + porter_add_vsp1_devices(); + #endif + porter_add_msiof_device(spi_bus, ARRAY_SIZE(spi_bus)); +-- +1.9.1 + diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/9999-Backport-fix-for-CVE-2016-5195.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/9999-Backport-fix-for-CVE-2016-5195.patch new file mode 100644 index 0000000..e7a143f --- /dev/null +++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/9999-Backport-fix-for-CVE-2016-5195.patch @@ -0,0 +1,68 @@ +From 8003e1524789537680204d44d5bf7a82561f8ba3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jan-Simon=20M=C3=B6ller?= <jsmoeller@linuxfoundation.org> +Date: Fri, 4 Nov 2016 20:58:46 +0100 +Subject: [PATCH] Backport fix for CVE-2016-5195 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Jan-Simon Möller <jsmoeller@linuxfoundation.org> +--- + include/linux/mm.h | 1 + + mm/memory.c | 14 ++++++++++++-- + 2 files changed, 13 insertions(+), 2 deletions(-) + +diff --git a/include/linux/mm.h b/include/linux/mm.h +index 3bf21c3..263b405 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -1702,6 +1702,7 @@ static inline struct page *follow_page(struct vm_area_struct *vma, + #define FOLL_HWPOISON 0x100 /* check page is hwpoisoned */ + #define FOLL_NUMA 0x200 /* force NUMA hinting page fault */ + #define FOLL_MIGRATION 0x400 /* wait for page to replace migration entry */ ++#define FOLL_COW 0x4000 /* internal GUP flag */ + + typedef int (*pte_fn_t)(pte_t *pte, pgtable_t token, unsigned long addr, + void *data); +diff --git a/mm/memory.c b/mm/memory.c +index 48aa275..3a3f316 100644 +--- a/mm/memory.c ++++ b/mm/memory.c +@@ -1462,6 +1462,16 @@ int zap_vma_ptes(struct vm_area_struct *vma, unsigned long address, + } + EXPORT_SYMBOL_GPL(zap_vma_ptes); + ++/* ++ * FOLL_FORCE can write to even unwritable pte's, but only ++ * after we've gone through a COW cycle and they are dirty. ++ */ ++static inline bool can_follow_write_pte(pte_t pte, unsigned int flags) ++{ ++ return pte_write(pte) || ++ ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pte_dirty(pte)); ++} ++ + /** + * follow_page_mask - look up a page descriptor from a user-virtual address + * @vma: vm_area_struct mapping @address +@@ -1569,7 +1579,7 @@ split_fallthrough: + } + if ((flags & FOLL_NUMA) && pte_numa(pte)) + goto no_page; +- if ((flags & FOLL_WRITE) && !pte_write(pte)) ++ if ((flags & FOLL_WRITE) && !can_follow_write_pte(pte, flags)) + goto unlock; + + page = vm_normal_page(vma, address, pte); +@@ -1876,7 +1886,7 @@ long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, + */ + if ((ret & VM_FAULT_WRITE) && + !(vma->vm_flags & VM_WRITE)) +- foll_flags &= ~FOLL_WRITE; ++ foll_flags |= FOLL_COW; + + cond_resched(); + } +-- +2.1.4 + diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/can-rcar.cfg b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/can-rcar.cfg new file mode 100644 index 0000000..5b16fb7 --- /dev/null +++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/can-rcar.cfg @@ -0,0 +1,3 @@ +CONFIG_CAN=y +CONFIG_CAN_VCAN=y +CONFIG_CAN_RCAR=y diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/smack/0055-Smack-Assign-smack_known_web-as-default-smk_in-label.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/smack/0055-Smack-Assign-smack_known_web-as-default-smk_in-label.patch new file mode 100644 index 0000000..18353d3 --- /dev/null +++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/smack/0055-Smack-Assign-smack_known_web-as-default-smk_in-label.patch @@ -0,0 +1,55 @@ +From 292f377160c78213af88b5cc069dbdaa08db17dd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Bollo?= <jose.bollo@iot.bzh> +Date: Wed, 2 Nov 2016 11:11:01 +0100 +Subject: [PATCH 55/56] Smack: Assign smack_known_web as default smk_in label + for kernel thread's socket +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This change fixes the bug associated with sockets owned by kernel threads. These +sockets, created usually by network devices' drivers tasks, received smk_in +label from the task that created them - the "floor" label in the most cases. The +result was that they were not able to receive data packets because of missing +smack rules. The main reason of the access deny is that the socket smk_in label +is placed as the object during smk check, kernel thread's capabilities are +omitted. + +Refers-to: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=7412301b76bd53ee53b860f611fc3b5b1c2245b5 +Change-Id: Icec88b0d51133df8d0a09ea8016233bde255af10 +Signed-off-by: Marcin Lis <m.lis@samsung.com> +Signed-off-by: José Bollo <jose.bollo@iot.bzh> +--- + security/smack/smack_lsm.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c +index 895fe5c..ff696e7 100644 +--- a/security/smack/smack_lsm.c ++++ b/security/smack/smack_lsm.c +@@ -2453,7 +2453,21 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, + static int smack_socket_post_create(struct socket *sock, int family, + int type, int protocol, int kern) + { +- if (family != PF_INET || sock->sk == NULL) ++ struct socket_smack *ssp; ++ ++ if (sock->sk == NULL) ++ return 0; ++ ++ /* ++ * Sockets created by kernel threads receive web label. ++ */ ++ if (unlikely(current->flags & PF_KTHREAD)) { ++ ssp = sock->sk->sk_security; ++ ssp->smk_in = &smack_known_web; ++ ssp->smk_out = &smack_known_web; ++ } ++ ++ if (family != PF_INET) + return 0; + /* + * Set the outbound netlbl. +-- +2.7.4 + diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/smack/0056-Smack-Assign-smack_known_web-label-for-kernel-thread.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/smack/0056-Smack-Assign-smack_known_web-label-for-kernel-thread.patch new file mode 100644 index 0000000..b045101 --- /dev/null +++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/smack/0056-Smack-Assign-smack_known_web-label-for-kernel-thread.patch @@ -0,0 +1,49 @@ +From ea1c9711146e251c809ecf7eb348b548ac6e967c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Bollo?= <jose.bollo@iot.bzh> +Date: Wed, 2 Nov 2016 11:01:15 +0100 +Subject: [PATCH 56/56] Smack: Assign smack_known_web label for kernel thread's + socket in the sk_alloc_security hook +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Creating struct sock by sk_alloc function in various kernel subsystems +like bluetooth dosen't call smack_socket_post_create(). In such case, +received sock label is the floor('_') label and makes access deny. + +Refers-to: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=7412301b76bd53ee53b860f611fc3b5b1c2245b5 +Refers-to: https://review.tizen.org/gerrit/#/c/80717/4 + +Change-Id: I614c5f0e6d59be5ca6b49f0581edfef79fc334cf +Signed-off-by: jooseong lee <jooseong.lee@samsung.com> +Signed-off-by: José Bollo <jose.bollo@iot.bzh> +--- + security/smack/smack_lsm.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c +index ff696e7..94914db 100644 +--- a/security/smack/smack_lsm.c ++++ b/security/smack/smack_lsm.c +@@ -2075,8 +2075,16 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) + if (ssp == NULL) + return -ENOMEM; + +- ssp->smk_in = skp; +- ssp->smk_out = skp; ++ /* ++ * Sockets created by kernel threads receive web label. ++ */ ++ if (unlikely(current->flags & PF_KTHREAD)) { ++ ssp->smk_in = &smack_known_web; ++ ssp->smk_out = &smack_known_web; ++ } else { ++ ssp->smk_in = skp; ++ ssp->smk_out = skp; ++ } + ssp->smk_packet = NULL; + + sk->sk_security = ssp; +-- +2.7.4 + diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/smack/0057-Smack-handles-socket-in-file_receive.patch b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/smack/0057-Smack-handles-socket-in-file_receive.patch new file mode 100644 index 0000000..ba02af8 --- /dev/null +++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas/smack/0057-Smack-handles-socket-in-file_receive.patch @@ -0,0 +1,61 @@ +From 99719d12de612819e06fc3d0741b7e2da119d61c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Bollo?= <jose.bollo@iot.bzh> +Date: Wed, 2 Nov 2016 18:32:32 +0100 +Subject: [PATCH] Smack: handles socket in file_receive +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The security context of sockets and the rules +of security are differents for sockets. + +This is a backport of http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=79be09350 + +Change-Id: Id520c9ca8f7ee8883523a0e4b40176524442db33 +Signed-off-by: José Bollo <jose.bollo@iot.bzh> +--- + security/smack/smack_lsm.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c +index 94914db..3b09524 100644 +--- a/security/smack/smack_lsm.c ++++ b/security/smack/smack_lsm.c +@@ -1638,9 +1638,34 @@ static int smack_file_receive(struct file *file) + int may = 0; + struct smk_audit_info ad; + struct inode *inode = file_inode(file); ++ struct socket *sock; ++ struct task_smack *tsp; ++ struct socket_smack *ssp; ++ ++ if (unlikely(IS_PRIVATE(inode))) ++ return 0; + + smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); + smk_ad_setfield_u_fs_path(&ad, file->f_path); ++ ++ if (S_ISSOCK(inode->i_mode)) { ++ sock = SOCKET_I(inode); ++ ssp = sock->sk->sk_security; ++ tsp = current_security(); ++ /* ++ * If the receiving process can't write to the ++ * passed socket or if the passed socket can't ++ * write to the receiving process don't accept ++ * the passed socket. ++ */ ++ rc = smk_access(tsp->smk_task, ssp->smk_out, MAY_WRITE, &ad); ++ rc = smk_bu_file(file, may, rc); ++ if (rc < 0) ++ return rc; ++ rc = smk_access(ssp->smk_in, tsp->smk_task, MAY_WRITE, &ad); ++ rc = smk_bu_file(file, may, rc); ++ return rc; ++ } + /* + * This code relies on bitmasks. + */ +-- +2.7.4 + diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas_3.10.bb b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas_3.10.bb index 31fac9a..ffe1ef8 100644 --- a/meta-rcar-gen2/recipes-kernel/linux/linux-renesas_3.10.bb +++ b/meta-rcar-gen2/recipes-kernel/linux/linux-renesas_3.10.bb @@ -12,24 +12,27 @@ PV_append = "+git${SRCREV}" PKGE = "1" RENESAS_BACKPORTS_URL="git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas-backport.git" -SRCREV = "b8ca8c397343f4233f9f68fc3a5bf8e1c9b88251" -SRC_URI = "${RENESAS_BACKPORTS_URL};protocol=git;branch=bsp/v3.10.31-ltsi/rcar-gen2-1.9.2 \ +SRCREV = "165e12ce2d7839e755debbec78dfa43b54345275" +SRC_URI = "${RENESAS_BACKPORTS_URL};protocol=git;branch=bsp/v3.10.31-ltsi/rcar-gen2-1.9.7 \ file://0001-kernel-add-support-for-gcc-5.patch \ file://0001-kernel-add-support-for-gcc-6.patch \ file://0001-arm-lager-Add-vmalloc-384M-to-bootargs-of-DTS.patch \ file://0001-arm-koelsch-Add-vmalloc-384M-to-bootargs-of-DTS.patch \ file://0001-arm-alt-Add-vmalloc-384M-to-bootargs-of-DTS.patch \ file://0001-arm-gose-Add-vmalloc-384M-to-bootargs-of-DTS.patch \ + file://0001-ASoC-ak4642-Replace-mdelay-function-to-msleep.patch \ " SRC_URI_append_porter = " \ file://0001-kernel-Silk-board-support.patch \ + file://0002-silk-reference-Add-DRM_RCAR_DU_CONNECT_VSP-configura.patch \ file://0002-kernel-silk-fix-ethernet-phy-irq.patch \ file://0003-kernel-silk-fix-sd-detect.patch \ file://0004-kernel-Revert-i2c-rcar-Support-ACK-by-HW-auto-restart-after-NACK.patch \ file://0006-Rcar-DU-add-RGB-connector.patch \ file://0007-SILK-add-i2c0.patch \ file://0008-Porter-board-support.patch \ + file://0009-porter-reference-Add-DRM_RCAR_DU_CONNECT_VSP-configu.patch \ file://0009-shmobile-add-atag-dtb-compat.patch \ file://0010-Silk-Add-missing-pins-handle-to-Eth.patch \ file://0011-Silk-Add-missing-DU-pins.patch \ @@ -55,12 +58,14 @@ SRC_URI_append_porter = " \ SRC_URI_append_silk = " \ file://0001-kernel-Silk-board-support.patch \ + file://0002-silk-reference-Add-DRM_RCAR_DU_CONNECT_VSP-configura.patch \ file://0002-kernel-silk-fix-ethernet-phy-irq.patch \ file://0003-kernel-silk-fix-sd-detect.patch \ file://0004-kernel-Revert-i2c-rcar-Support-ACK-by-HW-auto-restart-after-NACK.patch \ file://0006-Rcar-DU-add-RGB-connector.patch \ file://0007-SILK-add-i2c0.patch \ file://0008-Porter-board-support.patch \ + file://0009-porter-reference-Add-DRM_RCAR_DU_CONNECT_VSP-configu.patch \ file://0009-shmobile-add-atag-dtb-compat.patch \ file://0010-Silk-Add-missing-pins-handle-to-Eth.patch \ file://0011-Silk-Add-missing-DU-pins.patch \ @@ -145,6 +150,19 @@ SRC_URI_append_smack = " \ file://smack/0054-Smack-secmark-connections.patch \ " +# smack patches are applied if DISTRO_FEATURES has "smack" +# smack patches for handling bluetooth +SRC_URI_append_smack = " \ + file://smack/0055-Smack-Assign-smack_known_web-as-default-smk_in-label.patch \ + file://smack/0056-Smack-Assign-smack_known_web-label-for-kernel-thread.patch \ + file://smack/0057-Smack-handles-socket-in-file_receive.patch \ +" + +SRC_URI_append_porter = " file://can-rcar.cfg" + +# Backport fix for CVE-2016-5195 +SRC_URI_append = " file://9999-Backport-fix-for-CVE-2016-5195.patch " + S = "${WORKDIR}/git" KERNEL_DEFCONFIG = "shmobile_defconfig" @@ -152,3 +170,21 @@ KERNEL_DEFCONFIG = "shmobile_defconfig" do_configure_prepend() { install -m 0644 ${S}/arch/${ARCH}/configs/${KERNEL_DEFCONFIG} ${WORKDIR}/defconfig || die "No default configuration for ${MACHINE} / ${KERNEL_DEFCONFIG} available." } + +do_install_append(){ + # modprobe automatically at boot + if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then + install -d ${D}/${sysconfdir}/modules-load.d + touch ${D}/${sysconfdir}/modules-load.d/cluster-demo.conf + echo "mmngr" >> ${D}/${sysconfdir}/modules-load.d/cluster-demo.conf + echo "mmngrbuf" >> ${D}/${sysconfdir}/modules-load.d/cluster-demo.conf + echo "uvcs_cmn" >> ${D}/${sysconfdir}/modules-load.d/cluster-demo.conf + echo "s3ctl" >> ${D}/${sysconfdir}/modules-load.d/cluster-demo.conf + echo "vspm" >> ${D}/${sysconfdir}/modules-load.d/cluster-demo.conf + echo "fdpm" >> ${D}/${sysconfdir}/modules-load.d/cluster-demo.conf + fi +} + +FILES_kernel-modules += " \ + ${sysconfdir}/modules-load.d/cluster-demo.conf \ + " diff --git a/meta-rcar-gen2/recipes-kernel/linux/linux.inc b/meta-rcar-gen2/recipes-kernel/linux/linux.inc index 75a7141..6d1005f 100644 --- a/meta-rcar-gen2/recipes-kernel/linux/linux.inc +++ b/meta-rcar-gen2/recipes-kernel/linux/linux.inc @@ -16,7 +16,7 @@ UDEV_GE_141 ?= "1" KERNEL_ENABLE_CGROUPS ?= "1" # combine oe-core way with angstrom DISTRO_TYPE -DISTRO_TYPE ?= "${@base_contains("IMAGE_FEATURES", "debug-tweaks", "debug", "release",d)}" +DISTRO_TYPE ?= "${@bb.utils.contains("IMAGE_FEATURES", "debug-tweaks", "debug", "release",d)}" # Set the verbosity of kernel messages during runtime # You can define CMDLINE_DEBUG in your local.conf or distro.conf to override this behaviour @@ -37,6 +37,16 @@ kernel_configure_variable() { fi } +# returns all the elements from the src uri that are .cfg files +def find_cfgs(d): + sources=src_patches(d, True) + sources_list=[] + for s in sources: + if s.endswith('.cfg'): + sources_list.append(s) + + return sources_list + do_configure_prepend() { # Clean .config echo "" > ${B}/.config @@ -175,7 +185,7 @@ do_configure_prepend() { kernel_configure_variable BLK_DEV_LOOP y fi - if [ "x1" = "x${@base_contains("DISTRO_FEATURES", "usbgadget", "1", "",d)}" ]; then + if [ "x1" = "x${@bb.utils.contains("DISTRO_FEATURES", "usbgadget", "1", "",d)}" ]; then # activate USB-OTG & Gadget kernel_configure_variable USB_OTG y kernel_configure_variable USB_RENESAS_USBHS_UDC y @@ -201,6 +211,10 @@ do_configure_prepend() { # Remove all modified configs and add the rest to .config sed -e "${CONF_SED_SCRIPT}" < '${WORKDIR}/defconfig' >> '${B}/.config' + # add cfgs from SRC_URI. + cfgs="${@" ".join(find_cfgs(d))}" + cat ${cfgs} >> '${B}/.config' + yes '' | oe_runmake -C ${S} O=${B} oldconfig } @@ -216,31 +230,6 @@ do_configure_bluetooth() { kernel_configure_variable RFKILL m } -do_configure_append_porter() { - # Enable CAN - kernel_configure_variable CAN y - kernel_configure_variable CAN_VCAN y - kernel_configure_variable CAN_RCAR y - - yes '' | oe_runmake -C ${S} O=${B} oldconfig -} - -do_configure_append_smack() { - # Enable Smack - kernel_configure_variable IP_NF_SECURITY m - kernel_configure_variable IP6_NF_SECURITY m - kernel_configure_variable EXT2_FS_SECURITY y - kernel_configure_variable EXT3_FS_SECURITY y - kernel_configure_variable EXT4_FS_SECURITY y - kernel_configure_variable SECURITY y - kernel_configure_variable SECURITY_SMACK y - kernel_configure_variable TMPFS_XATTR y - - kernel_configure_variable DEFAULT_SECURITY "smack" - kernel_configure_variable DEFAULT_SECURITY_SMACK y - yes '' | oe_runmake -C ${S} O=${B} oldconfig -} - # Automatically depend on lzop-native if CONFIG_KERNEL_LZO is enabled python () { try: diff --git a/meta-rcar-gen2/recipes-kernel/mmngr-module/mmngr-kernel-module.bb b/meta-rcar-gen2/recipes-kernel/mmngr-module/mmngr-kernel-module.bb index 96b3de7..baf3433 100644 --- a/meta-rcar-gen2/recipes-kernel/mmngr-module/mmngr-kernel-module.bb +++ b/meta-rcar-gen2/recipes-kernel/mmngr-module/mmngr-kernel-module.bb @@ -1,7 +1,7 @@ require ../../include/rcar-gen2-modules-common.inc require ../../include/multimedia-control.inc -LICENSE = "GPLv2&MIT" +LICENSE = "GPLv2 & MIT" LIC_FILES_CHKSUM = "file://drv/GPL-COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \ file://drv/MIT-COPYING;md5=fea016ce2bdf2ec10080f69e9381d378 \ file://include/GPL-COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \ diff --git a/meta-rcar-gen2/recipes-kernel/mmngr-module/mmngrbuf-kernel-module.bb b/meta-rcar-gen2/recipes-kernel/mmngr-module/mmngrbuf-kernel-module.bb index bda21ed..120b5aa 100644 --- a/meta-rcar-gen2/recipes-kernel/mmngr-module/mmngrbuf-kernel-module.bb +++ b/meta-rcar-gen2/recipes-kernel/mmngr-module/mmngrbuf-kernel-module.bb @@ -1,6 +1,6 @@ require ../../include/rcar-gen2-modules-common.inc -LICENSE = "GPLv2&MIT" +LICENSE = "GPLv2 & MIT" DEPENDS = "linux-renesas" PN = "mmngrbuf-kernel-module" PR = "r0" diff --git a/meta-rcar-gen2/recipes-kernel/s3ctl-module/s3ctl-kernel-module.bb b/meta-rcar-gen2/recipes-kernel/s3ctl-module/s3ctl-kernel-module.bb index 141be11..493b2e9 100644 --- a/meta-rcar-gen2/recipes-kernel/s3ctl-module/s3ctl-kernel-module.bb +++ b/meta-rcar-gen2/recipes-kernel/s3ctl-module/s3ctl-kernel-module.bb @@ -1,6 +1,6 @@ require ../../include/rcar-gen2-modules-common.inc -LICENSE = "GPLv2&MIT" +LICENSE = "GPLv2 & MIT" LIC_FILES_CHKSUM = "file://drv/GPL-COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \ file://drv/MIT-COPYING;md5=fea016ce2bdf2ec10080f69e9381d378" DEPENDS = "linux-renesas" diff --git a/meta-rcar-gen2/recipes-kernel/scu-module/scu-kernel-module.bb b/meta-rcar-gen2/recipes-kernel/scu-module/scu-kernel-module.bb index ec392a8..d453ff5 100644 --- a/meta-rcar-gen2/recipes-kernel/scu-module/scu-kernel-module.bb +++ b/meta-rcar-gen2/recipes-kernel/scu-module/scu-kernel-module.bb @@ -1,6 +1,6 @@ require ../../include/rcar-gen2-modules-common.inc -LICENSE = "GPLv2&MIT" +LICENSE = "GPLv2 & MIT" LIC_FILES_CHKSUM = "file://src/include/GPL-COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \ file://src/include/MIT-COPYING;md5=fea016ce2bdf2ec10080f69e9381d378 \ " diff --git a/meta-rcar-gen2/recipes-kernel/ssp-module/ssp-kernel-module.bb b/meta-rcar-gen2/recipes-kernel/ssp-module/ssp-kernel-module.bb index 8159215..8b6d039 100644 --- a/meta-rcar-gen2/recipes-kernel/ssp-module/ssp-kernel-module.bb +++ b/meta-rcar-gen2/recipes-kernel/ssp-module/ssp-kernel-module.bb @@ -1,6 +1,6 @@ require ../../include/rcar-gen2-modules-common.inc -LICENSE = "GPLv2&MIT" +LICENSE = "GPLv2 & MIT" LIC_FILES_CHKSUM = "file://ssp/drv/GPL-COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \ file://ssp/drv/MIT-COPYING;md5=fea016ce2bdf2ec10080f69e9381d378 \ " diff --git a/meta-rcar-gen2/recipes-kernel/uvcs-module/uvcs-kernel-module.bb b/meta-rcar-gen2/recipes-kernel/uvcs-module/uvcs-kernel-module.bb index 5212494..3ed5287 100644 --- a/meta-rcar-gen2/recipes-kernel/uvcs-module/uvcs-kernel-module.bb +++ b/meta-rcar-gen2/recipes-kernel/uvcs-module/uvcs-kernel-module.bb @@ -1,6 +1,6 @@ require ../../include/rcar-gen2-modules-common.inc -LICENSE = "GPLv2&MIT" +LICENSE = "GPLv2 & MIT" LIC_FILES_CHKSUM = "file://uvcs/include/GPL-COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \ file://uvcs/include/MIT-COPYING;md5=fea016ce2bdf2ec10080f69e9381d378 \ " diff --git a/meta-rcar-gen2/recipes-kernel/vspm-module/vsp2-kernel-module.bb b/meta-rcar-gen2/recipes-kernel/vspm-module/vsp2-kernel-module.bb new file mode 100644 index 0000000..a87314a --- /dev/null +++ b/meta-rcar-gen2/recipes-kernel/vspm-module/vsp2-kernel-module.bb @@ -0,0 +1,58 @@ +require ../../include/rcar-gen2-modules-common.inc + +LICENSE = "GPLv2&MIT" +LIC_FILES_CHKSUM = " \ + file://GPL-COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \ + file://MIT-COPYING;md5=fea016ce2bdf2ec10080f69e9381d378 \ +" + +DEPENDS = "linux-renesas vspm-kernel-module" +PN = "vsp2-kernel-module" +PR = "r0" + +SRCREV = "c231aff0fba0a2c559968098e5573050a1aa336d" +SRC_URI = " \ + git://github.com/renesas-devel/vsp2driver.git;protocol=git;branch=RCAR-GEN2/1.0.0 \ +" +S = "${WORKDIR}/git" + +do_configure[noexec] = "1" +do_compile() { + export VSP2_VSPMDIR=${KERNELSRC}/include + export VSP2_VSPMSYMVERS=vspm.symvers + cd ${S}/drv + make all ARCH=arm +} + +do_install() { + # Create destination folder + mkdir -p ${D}/lib/modules/${KERNEL_VERSION}/extra/ ${D}/usr/src/kernel/include/ + + # Copy kernel module + cp -f ${S}/drv/vsp2.ko ${D}/lib/modules/${KERNEL_VERSION}/extra/ + + # Copy shared library for reference from other modules + cp -f ${S}/drv/Module.symvers ${D}/usr/src/kernel/include/vsp2.symvers + cp -f ${S}/drv/Module.symvers ${KERNELSRC}/include/vsp2.symvers +} + +PACKAGES = "\ + ${PN} \ + ${PN}-dev \ +" + +FILES_${PN} = " \ + /lib/modules/${KERNEL_VERSION}/extra/vsp2.ko \ + ${sysconfdir}/* \ +" + +FILES_${PN}-dev = " \ + /usr/src/kernel/include/vsp2.symvers \ +" +RPROVIDES_${PN} += "vsp2-kernel-module" +INHIBIT_PACKAGE_DEBUG_SPLIT = "1" + +ALLOW_EMPTY_kernel-module-vsp2 = "1" + +# Autoload VSP2Driver +KERNEL_MODULE_AUTOLOAD = "vsp2" diff --git a/meta-rcar-gen2/recipes-kernel/vspm-module/vspm-kernel-module.bb b/meta-rcar-gen2/recipes-kernel/vspm-module/vspm-kernel-module.bb index 8e56614..2b47298 100644 --- a/meta-rcar-gen2/recipes-kernel/vspm-module/vspm-kernel-module.bb +++ b/meta-rcar-gen2/recipes-kernel/vspm-module/vspm-kernel-module.bb @@ -1,6 +1,6 @@ require ../../include/rcar-gen2-modules-common.inc -LICENSE = "GPLv2&MIT" +LICENSE = "GPLv2 & MIT" LIC_FILES_CHKSUM = "file://vspm/drv/GPL-COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \ file://vspm/drv/MIT-COPYING;md5=fea016ce2bdf2ec10080f69e9381d378 \ " diff --git a/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0001-omx-videodec-add-planebuf-to-allocation-request.patch b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0001-omx-videodec-add-planebuf-to-allocation-request.patch new file mode 100644 index 0000000..d863414 --- /dev/null +++ b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0001-omx-videodec-add-planebuf-to-allocation-request.patch @@ -0,0 +1,85 @@ +diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c +index c5b69ab..647ac88 100644 +--- a/omx/gstomxvideodec.c ++++ b/omx/gstomxvideodec.c +@@ -581,7 +581,7 @@ gst_omx_buffer_pool_free_buffer (GstBufferPool * bpool, GstBuffer * buffer) + #ifdef HAVE_MMNGRBUF + static GstBuffer * + gst_omx_buffer_pool_request_videosink_buffer_creation (GstOMXBufferPool * pool, +- gint dmabuf_fd[GST_VIDEO_MAX_PLANES], gint stride[GST_VIDEO_MAX_PLANES]) ++ gint dmabuf_fd[GST_VIDEO_MAX_PLANES], gpointer plane_buf[GST_VIDEO_MAX_PLANES], gint stride[GST_VIDEO_MAX_PLANES]) + { + GstQuery *query; + GValue val = { 0, }; +@@ -590,6 +590,7 @@ gst_omx_buffer_pool_request_videosink_buffer_creation (GstOMXBufferPool * pool, + GstBuffer *buffer; + GArray *dmabuf_array; + GArray *stride_array; ++ GArray *planebuf_array; + gint n_planes; + gint i; + +@@ -598,11 +599,13 @@ gst_omx_buffer_pool_request_videosink_buffer_creation (GstOMXBufferPool * pool, + + dmabuf_array = g_array_new (FALSE, FALSE, sizeof (gint)); + stride_array = g_array_new (FALSE, FALSE, sizeof (gint)); ++ planebuf_array = g_array_new (FALSE, FALSE, sizeof (gpointer)); + + n_planes = GST_VIDEO_INFO_N_PLANES (&pool->video_info); + for (i = 0; i < n_planes; i++) { + g_array_append_val (dmabuf_array, dmabuf_fd[i]); + g_array_append_val (stride_array, stride[i]); ++ g_array_append_val (planebuf_array, plane_buf[i]); + } + + structure = gst_structure_new ("videosink_buffer_creation_request", +@@ -610,6 +613,7 @@ gst_omx_buffer_pool_request_videosink_buffer_creation (GstOMXBufferPool * pool, + "height", G_TYPE_INT, pool->port->port_def.format.video.nFrameHeight, + "stride", G_TYPE_ARRAY, stride_array, + "dmabuf", G_TYPE_ARRAY, dmabuf_array, ++ "planebuf", G_TYPE_ARRAY, planebuf_array, + "allocator", G_TYPE_POINTER, &val, + "format", G_TYPE_STRING, + gst_video_format_to_string (pool->video_info.finfo->format), +@@ -704,6 +708,7 @@ gst_omx_buffer_pool_acquire_buffer (GstBufferPool * bpool, + gint i; + gint dmabuf_fd[GST_VIDEO_MAX_PLANES]; + gint plane_size[GST_VIDEO_MAX_PLANES]; ++ gpointer plane_buf[GST_VIDEO_MAX_PLANES]; + guint phys_addr; + OMXR_MC_VIDEO_DECODERESULTTYPE *decode_res = + (OMXR_MC_VIDEO_DECODERESULTTYPE *) omx_buf-> +@@ -730,6 +735,7 @@ gst_omx_buffer_pool_acquire_buffer (GstBufferPool * bpool, + + plane_size[0] = vmeta->stride[0] * + GST_VIDEO_INFO_COMP_HEIGHT (&pool->video_info, 0); ++ plane_buf[0] = omx_buf->omx_buf->pBuffer; + + /* Export dmabuf file descriptors from second and subsequent planes */ + n_planes = GST_VIDEO_INFO_N_PLANES (&pool->video_info); +@@ -737,6 +743,7 @@ gst_omx_buffer_pool_acquire_buffer (GstBufferPool * bpool, + phys_addr = (guint) decode_res->pvPhysImageAddressY + vmeta->offset[i]; + plane_size[i] = vmeta->stride[i] * + GST_VIDEO_INFO_COMP_HEIGHT (&pool->video_info, i); ++ plane_buf[i] = omx_buf->omx_buf->pBuffer + vmeta->offset[i]; + + if (!gst_omx_buffer_pool_export_dmabuf (pool, phys_addr, plane_size[i], + page_size, &vdbuf_data->id_export[i], &dmabuf_fd[i])) { +@@ -747,7 +754,7 @@ gst_omx_buffer_pool_acquire_buffer (GstBufferPool * bpool, + + if (pool->vsink_buf_req_supported) + new_buf = gst_omx_buffer_pool_request_videosink_buffer_creation (pool, +- dmabuf_fd, vmeta->stride); ++ dmabuf_fd, plane_buf, vmeta->stride); + else { + GstVideoMeta *new_meta; + +@@ -1947,6 +1954,8 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self) + goto caps_failed; + } + ++ /* ...force clearing of reconfiguration flag to prevent subsequent buffers allocation */ ++ gst_pad_check_reconfigure(GST_VIDEO_DECODER_SRC_PAD(self)); + gst_video_codec_state_unref (state); + + GST_VIDEO_DECODER_STREAM_UNLOCK (self); diff --git a/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0002-Fixed-memory-corruption-and-bad-access.patch b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0002-Fixed-memory-corruption-and-bad-access.patch new file mode 100644 index 0000000..354a7a9 --- /dev/null +++ b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0002-Fixed-memory-corruption-and-bad-access.patch @@ -0,0 +1,65 @@ +From 3e528cda6fb9d0da2be52e18a305096cf6e37528 Mon Sep 17 00:00:00 2001 +From: Andrey Vostrikov <andrey.vostrikov@cogentembedded.com> +Date: Sat, 18 Jul 2015 15:52:59 +0300 +Subject: [PATCH] Fixed memory corruption and bad access + +--- + omx/gstomxh264dec.c | 4 ++-- + omx/gstomxvideodec.c | 12 ++++++------ + 2 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/omx/gstomxh264dec.c b/omx/gstomxh264dec.c +index 7799e69..5509cc0 100644 +--- a/omx/gstomxh264dec.c ++++ b/omx/gstomxh264dec.c +@@ -104,7 +104,7 @@ gst_omx_h264_dec_retrieve_sps_pps (GstOMXH264Dec * self, guint8 * data) + + sps_num = ptr[5] & 0x1f; /* reserved(3bit) + numOfSequenceParameterSets(uint 5bit) */ + +- sps_size_list = g_malloc (sps_num); ++ sps_size_list = g_malloc (sps_num * sizeof (guint)); + if (!sps_size_list) { + GST_ERROR_OBJECT (self, "failed g_malloc"); + return NULL; +@@ -119,7 +119,7 @@ gst_omx_h264_dec_retrieve_sps_pps (GstOMXH264Dec * self, guint8 * data) + } + + pps_num = *ptr++; /* numOfPictureParameterSets (unint 8bit) */ +- pps_size_list = g_malloc (pps_num); ++ pps_size_list = g_malloc (pps_num * sizeof (guint)); + if (!pps_size_list) { + GST_ERROR_OBJECT (self, "failed g_malloc"); + g_free (sps_size_list); +diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c +index c5b69ab..4a9706f 100644 +--- a/omx/gstomxvideodec.c ++++ b/omx/gstomxvideodec.c +@@ -563,10 +563,12 @@ gst_omx_buffer_pool_free_buffer (GstBufferPool * bpool, GstBuffer * buffer) + gst_omx_buffer_data_quark); + #ifdef HAVE_MMNGRBUF + if (self->use_dmabuf) { +- vdbuf_data = (GstOMXVideoDecBufferData *) omx_buf->private_data; +- for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) +- if (vdbuf_data->id_export[i] >= 0) +- mmngr_export_end_in_user (vdbuf_data->id_export[i]); ++ vdbuf_data = (GstOMXVideoDecBufferData *) omx_buf->private_data; ++ if (vdbuf_data) { ++ for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) ++ if (vdbuf_data->id_export[i] >= 0) ++ mmngr_export_end_in_user (vdbuf_data->id_export[i]); ++ } + } + #endif + g_slice_free (GstOMXVideoDecBufferData, omx_buf->private_data); +@@ -1684,8 +1686,6 @@ gst_omx_video_dec_deallocate_output_buffers (GstOMXVideoDec * self) + + static void GstOMXBufCallbackfunc (struct GstOMXBufferCallback *release) + { +- gint i; +- + if (!release) + return; + +-- +2.1.4 + diff --git a/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0003-omxvideoenc-export-dmafd-buffer-through-own-buffer-p.patch b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0003-omxvideoenc-export-dmafd-buffer-through-own-buffer-p.patch new file mode 100644 index 0000000..23a3dfe --- /dev/null +++ b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0003-omxvideoenc-export-dmafd-buffer-through-own-buffer-p.patch @@ -0,0 +1,2759 @@ +From dcf585068bbb591431a999656359627cccd38716 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Thu, 25 Aug 2016 18:37:44 +0300 +Subject: [PATCH 03/10] omxvideoenc: export dmafd buffer through own buffer + pool + + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + configure.ac | 17 + + omx/Makefile.am | 1 + + omx/gstomxbufferpool.c | 845 +++++++++++++++++++++++++++++++++++++++++++ + omx/gstomxbufferpool.h | 106 ++++++ + omx/gstomxvideodec.c | 924 +----------------------------------------------- + omx/gstomxvideoenc.c | 578 ++++++++++++++++++++++-------- + omx/gstomxvideoenc.h | 11 + + 7 files changed, 1420 insertions(+), 1062 deletions(-) + create mode 100644 omx/gstomxbufferpool.c + create mode 100644 omx/gstomxbufferpool.h + +diff --git a/configure.ac b/configure.ac +index 6aae527..57f5ae9 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -245,6 +245,23 @@ AC_CHECK_LIB([mmngrbuf], [mmngr_export_start_in_user], + ]) + fi + ++dnl check OMXR_Extension_video.h ++AC_CHECK_HEADER([OMXR_Extension_video.h], ++ [AC_DEFINE(HAVE_VIDEOR_EXT, 1, [Define if you have OMXR_Extension_video.h header])], ++ [], ++ [AC_INCLUDES_DEFAULT]) ++dnl check OMXR_Extension_vecmn.h ++AC_CHECK_HEADER([OMXR_Extension_vecmn.h], ++ [AC_DEFINE(HAVE_VIDEOENC_EXT, 1, [Define if you have OMXR_Extension_vecmn.h header])], ++ [], ++ [AC_INCLUDES_DEFAULT]) ++ ++dnl check OMXR_Extension_vdcmn.h ++AC_CHECK_HEADER([OMXR_Extension_vdcmn.h], ++ [AC_DEFINE(HAVE_VIDEODEC_EXT, 1, [Define if you have OMXR_Extension_vdcmn.h header])], ++ [], ++ [AC_INCLUDES_DEFAULT]) ++ + dnl check page alignment option for NV12 planes + AC_ARG_ENABLE([nv12-page-alignment], + [AS_HELP_STRING([--enable-nv12-page-alignment], +diff --git a/omx/Makefile.am b/omx/Makefile.am +index 3ec6173..3619281 100644 +--- a/omx/Makefile.am ++++ b/omx/Makefile.am +@@ -12,6 +12,7 @@ endif + + libgstomx_la_SOURCES = \ + gstomx.c \ ++ gstomxbufferpool.c \ + gstomxvideodec.c \ + gstomxvideoenc.c \ + gstomxaudioenc.c \ +diff --git a/omx/gstomxbufferpool.c b/omx/gstomxbufferpool.c +new file mode 100644 +index 0000000..2585a72 +--- /dev/null ++++ b/omx/gstomxbufferpool.c +@@ -0,0 +1,845 @@ ++/* ++ * 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> ++ * Copyright (C) 2015, Renesas Electronics Corporation ++ * ++ * 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 "gstomxbufferpool.h" ++#include "gstomxvideodec.h" ++#include "gstomxvideoenc.h" ++#include "gst/allocators/gstdmabuf.h" ++#ifdef HAVE_MMNGRBUF ++#include "mmngr_buf_user_public.h" ++#endif ++#ifdef HAVE_VIDEODEC_EXT ++#include "OMXR_Extension_vdcmn.h" ++#endif ++#ifdef HAVE_VIDEOENC_EXT ++#include "OMXR_Extension_vecmn.h" ++#endif ++#include <unistd.h> /* getpagesize() */ ++ ++/** ++ * GST_ROUND_UP_N: ++ * @num: integrer value to round up ++ * @align: a power of two to round up to ++ * ++ * Rounds an integer value up to the next multiple of @align. @align MUST be a ++ * power of two. ++ */ ++#define GST_ROUND_UP_N(num,align) ((((num) + ((align) - 1)) & ~((align) - 1))) ++ ++GST_DEBUG_CATEGORY_STATIC (gst_omx_buffer_pool_debug_category); ++#define GST_CAT_DEFAULT gst_omx_buffer_pool_debug_category ++ ++typedef struct _GstOMXMemory GstOMXMemory; ++typedef struct _GstOMXMemoryAllocator GstOMXMemoryAllocator; ++typedef struct _GstOMXMemoryAllocatorClass GstOMXMemoryAllocatorClass; ++ ++struct _GstOMXMemory ++{ ++ GstMemory mem; ++ ++ GstOMXBuffer *buf; ++}; ++ ++struct _GstOMXMemoryAllocator ++{ ++ GstAllocator parent; ++}; ++ ++struct _GstOMXMemoryAllocatorClass ++{ ++ GstAllocatorClass parent_class; ++}; ++ ++#define GST_OMX_MEMORY_TYPE "openmax" ++ ++static GstMemory * ++gst_omx_memory_allocator_alloc_dummy (GstAllocator * allocator, gsize size, ++ GstAllocationParams * params) ++{ ++ g_assert_not_reached (); ++ return NULL; ++} ++ ++static void ++gst_omx_memory_allocator_free (GstAllocator * allocator, GstMemory * mem) ++{ ++ GstOMXMemory *omem = (GstOMXMemory *) mem; ++ ++ /* TODO: We need to remember which memories are still used ++ * so we can wait until everything is released before allocating ++ * new memory ++ */ ++ ++ g_slice_free (GstOMXMemory, omem); ++} ++ ++static gpointer ++gst_omx_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags) ++{ ++ GstOMXMemory *omem = (GstOMXMemory *) mem; ++ ++ return omem->buf->omx_buf->pBuffer + omem->mem.offset; ++} ++ ++static void ++gst_omx_memory_unmap (GstMemory * mem) ++{ ++} ++ ++static GstMemory * ++gst_omx_memory_share (GstMemory * mem, gssize offset, gssize size) ++{ ++ g_assert_not_reached (); ++ return NULL; ++} ++ ++GType gst_omx_memory_allocator_get_type (void); ++G_DEFINE_TYPE (GstOMXMemoryAllocator, gst_omx_memory_allocator, ++ GST_TYPE_ALLOCATOR); ++ ++#define GST_TYPE_OMX_MEMORY_ALLOCATOR (gst_omx_memory_allocator_get_type()) ++#define GST_IS_OMX_MEMORY_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_OMX_MEMORY_ALLOCATOR)) ++ ++static void ++gst_omx_memory_allocator_class_init (GstOMXMemoryAllocatorClass * klass) ++{ ++ GstAllocatorClass *allocator_class; ++ ++ allocator_class = (GstAllocatorClass *) klass; ++ ++ allocator_class->alloc = gst_omx_memory_allocator_alloc_dummy; ++ allocator_class->free = gst_omx_memory_allocator_free; ++} ++ ++static void ++gst_omx_memory_allocator_init (GstOMXMemoryAllocator * allocator) ++{ ++ GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator); ++ ++ alloc->mem_type = GST_OMX_MEMORY_TYPE; ++ alloc->mem_map = gst_omx_memory_map; ++ alloc->mem_unmap = gst_omx_memory_unmap; ++ alloc->mem_share = gst_omx_memory_share; ++ ++ /* default copy & is_span */ ++ ++ GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC); ++} ++ ++static GstMemory * ++gst_omx_memory_allocator_alloc (GstAllocator * allocator, GstMemoryFlags flags, ++ GstOMXBuffer * buf) ++{ ++ GstOMXMemory *mem; ++ gint align; ++ ++ /* FIXME: We don't allow sharing because we need to know ++ * when the memory becomes unused and can only then put ++ * it back to the pool. Which is done in the pool's release ++ * function ++ */ ++ flags |= GST_MEMORY_FLAG_NO_SHARE; ++ ++ /* GStreamer uses a bitmask for the alignment while ++ * OMX uses the alignment itself. So we have to convert ++ * here */ ++ align = buf->port->port_def.nBufferAlignment; ++ if (align > 0) ++ align -= 1; ++ if (((align + 1) & align) != 0) { ++ GST_WARNING ("Invalid alignment that is not a power of two: %u", ++ (guint) buf->port->port_def.nBufferAlignment); ++ align = 0; ++ } ++ ++ mem = g_slice_new (GstOMXMemory); ++ /* the shared memory is always readonly */ ++ gst_memory_init (GST_MEMORY_CAST (mem), flags, allocator, NULL, ++ buf->omx_buf->nAllocLen, align, 0, buf->omx_buf->nAllocLen); ++ ++ mem->buf = buf; ++ ++ return GST_MEMORY_CAST (mem); ++} ++ ++/* Buffer pool for the buffers of an OpenMAX port. ++ * ++ * This pool is only used if we either passed buffers from another ++ * pool to the OMX port or provide the OMX buffers directly to other ++ * elements. ++ * ++ * ++ * A buffer is in the pool if it is currently owned by the port, ++ * i.e. after OMX_{Fill,Empty}ThisBuffer(). A buffer is outside ++ * the pool after it was taken from the port after it was handled ++ * by the port, i.e. {Empty,Fill}BufferDone. ++ * ++ * Buffers can be allocated by us (OMX_AllocateBuffer()) or allocated ++ * by someone else and (temporarily) passed to this pool ++ * (OMX_UseBuffer(), OMX_UseEGLImage()). In the latter case the pool of ++ * the buffer will be overriden, and restored in free_buffer(). Other ++ * buffers are just freed there. ++ * ++ * The pool always has a fixed number of minimum and maximum buffers ++ * and these are allocated while starting the pool and released afterwards. ++ * They correspond 1:1 to the OMX buffers of the port, which are allocated ++ * before the pool is started. ++ * ++ * Acquiring a buffer from this pool happens after the OMX buffer has ++ * been acquired from the port. gst_buffer_pool_acquire_buffer() is ++ * supposed to return the buffer that corresponds to the OMX buffer. ++ * ++ * For buffers provided to upstream, the buffer will be passed to ++ * the component manually when it arrives and then unreffed. If the ++ * buffer is released before reaching the component it will be just put ++ * back into the pool as if EmptyBufferDone has happened. If it was ++ * passed to the component, it will be back into the pool when it was ++ * released and EmptyBufferDone has happened. ++ * ++ * For buffers provided to downstream, the buffer will be returned ++ * back to the component (OMX_FillThisBuffer()) when it is released. ++ */ ++ ++static GQuark gst_omx_buffer_data_quark = 0; ++ ++#define DEBUG_INIT \ ++ GST_DEBUG_CATEGORY_INIT (gst_omx_buffer_pool_debug_category, "omxbufferpool", 0, \ ++ "debug category for gst-omx buffer pool base class"); ++ ++G_DEFINE_TYPE_WITH_CODE (GstOMXBufferPool, gst_omx_buffer_pool, ++ GST_TYPE_BUFFER_POOL, DEBUG_INIT); ++ ++static void gst_omx_buffer_pool_free_buffer (GstBufferPool * bpool, ++ GstBuffer * buffer); ++ ++static gboolean ++gst_omx_buffer_pool_start (GstBufferPool * bpool) ++{ ++ GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool); ++ ++ /* Only allow to start the pool if we still are attached ++ * to a component and port */ ++ GST_OBJECT_LOCK (pool); ++ if (!pool->component || !pool->port) { ++ GST_OBJECT_UNLOCK (pool); ++ return FALSE; ++ } ++ GST_OBJECT_UNLOCK (pool); ++ ++ return ++ GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->start (bpool); ++} ++ ++static gboolean ++gst_omx_buffer_pool_stop (GstBufferPool * bpool) ++{ ++ GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool); ++ gint i = 0; ++ ++ /* When not using the default GstBufferPool::GstAtomicQueue then ++ * GstBufferPool::free_buffer is not called while stopping the pool ++ * (because the queue is empty) */ ++ for (i = 0; i < pool->buffers->len; i++) ++ GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->release_buffer ++ (bpool, g_ptr_array_index (pool->buffers, i)); ++ ++ /* Remove any buffers that are there */ ++ g_ptr_array_set_size (pool->buffers, 0); ++ ++ if (pool->caps) ++ gst_caps_unref (pool->caps); ++ pool->caps = NULL; ++ ++ pool->add_videometa = FALSE; ++ ++ return GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->stop (bpool); ++} ++ ++static const gchar ** ++gst_omx_buffer_pool_get_options (GstBufferPool * bpool) ++{ ++ static const gchar *raw_video_options[] = ++ { GST_BUFFER_POOL_OPTION_VIDEO_META, NULL }; ++ static const gchar *options[] = { NULL }; ++ GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool); ++ ++ GST_OBJECT_LOCK (pool); ++ if (pool->port && pool->port->port_def.eDomain == OMX_PortDomainVideo ++ && pool->port->port_def.format.video.eCompressionFormat == ++ OMX_VIDEO_CodingUnused) { ++ GST_OBJECT_UNLOCK (pool); ++ return raw_video_options; ++ } ++ GST_OBJECT_UNLOCK (pool); ++ ++ return options; ++} ++ ++static gboolean ++gst_omx_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config) ++{ ++ GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool); ++ GstCaps *caps; ++ ++ GST_OBJECT_LOCK (pool); ++ ++ if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL)) ++ goto wrong_config; ++ ++ if (caps == NULL) ++ goto no_caps; ++ ++ if (pool->port && pool->port->port_def.eDomain == OMX_PortDomainVideo ++ && pool->port->port_def.format.video.eCompressionFormat == ++ OMX_VIDEO_CodingUnused) { ++ GstVideoInfo info; ++ ++ /* now parse the caps from the config */ ++ if (!gst_video_info_from_caps (&info, caps)) ++ goto wrong_video_caps; ++ ++ /* enable metadata based on config of the pool */ ++ pool->add_videometa = ++ gst_buffer_pool_config_has_option (config, ++ GST_BUFFER_POOL_OPTION_VIDEO_META); ++ ++ pool->video_info = info; ++ } ++ ++ if (pool->caps) ++ gst_caps_unref (pool->caps); ++ pool->caps = gst_caps_ref (caps); ++ ++ GST_OBJECT_UNLOCK (pool); ++ ++ return GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->set_config ++ (bpool, config); ++ ++ /* ERRORS */ ++wrong_config: ++ { ++ GST_OBJECT_UNLOCK (pool); ++ GST_WARNING_OBJECT (pool, "invalid config"); ++ return FALSE; ++ } ++no_caps: ++ { ++ GST_OBJECT_UNLOCK (pool); ++ GST_WARNING_OBJECT (pool, "no caps in config"); ++ return FALSE; ++ } ++wrong_video_caps: ++ { ++ GST_OBJECT_UNLOCK (pool); ++ GST_WARNING_OBJECT (pool, ++ "failed getting geometry from caps %" GST_PTR_FORMAT, caps); ++ return FALSE; ++ } ++} ++ ++#if defined (HAVE_MMNGRBUF) && defined (HAVE_VIDEODEC_EXT) ++static gboolean ++gst_omx_buffer_pool_export_dmabuf (GstOMXBufferPool * pool, ++ guint phys_addr, gint size, gint * id_export, gint * dmabuf_fd) ++{ ++ gint res; ++ ++ res = ++ mmngr_export_start_in_user (id_export, ++ (gsize) size, phys_addr, dmabuf_fd); ++ if (res != R_MM_OK) { ++ GST_ERROR_OBJECT (pool, ++ "mmngr_export_start_in_user failed (phys_addr:0x%08x)", phys_addr); ++ return FALSE; ++ } ++ GST_DEBUG_OBJECT (pool, ++ "Export dmabuf:%d id_export:%d (phys_addr:0x%08x)", *dmabuf_fd, ++ *id_export, phys_addr); ++ ++ return TRUE; ++} ++ ++/* This function will create a GstBuffer contain dmabuf_fd of decoded ++ * video got from Media Component ++ */ ++static GstBuffer * ++gst_omx_buffer_pool_create_buffer_contain_dmabuf (GstOMXBufferPool * self, ++ GstOMXBuffer * omx_buf, gint * stride, gsize * offset) ++{ ++ gint dmabuf_fd[GST_VIDEO_MAX_PLANES]; ++ gint plane_size[GST_VIDEO_MAX_PLANES]; ++ gint plane_size_ext[GST_VIDEO_MAX_PLANES]; ++ gint dmabuf_id[GST_VIDEO_MAX_PLANES]; ++ gint page_offset[GST_VIDEO_MAX_PLANES]; ++ GstBuffer *new_buf; ++ gint i; ++ gint page_size; ++ guint phys_addr = 0; ++ ++ new_buf = gst_buffer_new (); ++ page_size = getpagesize (); ++ ++ GST_DEBUG_OBJECT (self, "Creating dmabuf mem pBuffer=%p", ++ omx_buf->omx_buf->pBuffer); ++ ++ if (GST_IS_OMX_VIDEO_DEC (self->element)) { ++ OMXR_MC_VIDEO_DECODERESULTTYPE *decode_res = ++ (OMXR_MC_VIDEO_DECODERESULTTYPE *) omx_buf->omx_buf->pOutputPortPrivate; ++ phys_addr = decode_res->pvPhysImageAddressY; ++ } else if (GST_IS_OMX_VIDEO_ENC (self->element)) { ++ /* private data is a physical address of HW buffer */ ++ phys_addr = (guint) omx_buf->omx_buf->pInputPortPrivate; ++ } ++ ++ if (phys_addr == 0) { ++ GST_ERROR_OBJECT (self, "Invalid phys addr for OMX buffer"); ++ return NULL; ++ } ++ ++ for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&self->video_info); i++) { ++ guint plane_addr = 0; ++ GstMemory *mem; ++ ++ plane_addr = phys_addr + offset[i]; ++ /* Calculate offset between physical address and page boundary */ ++ page_offset[i] = plane_addr & (page_size - 1); ++ ++ plane_size[i] = stride[i] * ++ GST_VIDEO_INFO_COMP_HEIGHT (&self->video_info, i); ++ ++ /* When downstream plugins do mapping from dmabuf fd it requires ++ * mapping from boundary page and size align for page size so ++ * memory for plane must increase to handle for this case */ ++ plane_size_ext[i] = GST_ROUND_UP_N (plane_size[i] + page_offset[i], ++ page_size); ++ ++ if (!gst_omx_buffer_pool_export_dmabuf (self, plane_addr, ++ plane_size_ext[i], &dmabuf_id[i], &dmabuf_fd[i])) { ++ GST_ERROR_OBJECT (self, "dmabuf exporting failed"); ++ return NULL; ++ } ++ ++ g_array_append_val (self->id_array, dmabuf_id[i]); ++ /* Set offset's information */ ++ mem = gst_dmabuf_allocator_alloc (self->allocator, dmabuf_fd[i], ++ plane_size_ext[i]); ++ mem->offset = page_offset[i]; ++ mem->size = plane_size[i]; ++ gst_buffer_append_memory (new_buf, mem); ++ } ++ ++ g_ptr_array_add (self->buffers, new_buf); ++ gst_buffer_add_video_meta_full (new_buf, GST_VIDEO_FRAME_FLAG_NONE, ++ GST_VIDEO_INFO_FORMAT (&self->video_info), ++ GST_VIDEO_INFO_WIDTH (&self->video_info), ++ GST_VIDEO_INFO_HEIGHT (&self->video_info), ++ GST_VIDEO_INFO_N_PLANES (&self->video_info), offset, stride); ++ ++ return new_buf; ++} ++#endif ++ ++static GstFlowReturn ++gst_omx_buffer_pool_alloc_buffer (GstBufferPool * bpool, ++ GstBuffer ** buffer, GstBufferPoolAcquireParams * params) ++{ ++ GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool); ++ GstBuffer *buf; ++ GstOMXBuffer *omx_buf; ++ ++ g_return_val_if_fail (pool->allocating, GST_FLOW_ERROR); ++ ++ omx_buf = g_ptr_array_index (pool->port->buffers, pool->current_buffer_index); ++ g_return_val_if_fail (omx_buf != NULL, GST_FLOW_ERROR); ++ ++ if (pool->other_pool) { ++ guint i, n; ++ ++ buf = g_ptr_array_index (pool->buffers, pool->current_buffer_index); ++ g_assert (pool->other_pool == buf->pool); ++ gst_object_replace ((GstObject **) & buf->pool, NULL); ++ ++ n = gst_buffer_n_memory (buf); ++ for (i = 0; i < n; i++) { ++ GstMemory *mem = gst_buffer_peek_memory (buf, i); ++ ++ /* FIXME: We don't allow sharing because we need to know ++ * when the memory becomes unused and can only then put ++ * it back to the pool. Which is done in the pool's release ++ * function ++ */ ++ GST_MINI_OBJECT_FLAG_SET (mem, GST_MEMORY_FLAG_NO_SHARE); ++ } ++ ++ if (pool->add_videometa) { ++ GstVideoMeta *meta; ++ ++ meta = gst_buffer_get_video_meta (buf); ++ if (!meta) { ++ gst_buffer_add_video_meta (buf, GST_VIDEO_FRAME_FLAG_NONE, ++ GST_VIDEO_INFO_FORMAT (&pool->video_info), ++ GST_VIDEO_INFO_WIDTH (&pool->video_info), ++ GST_VIDEO_INFO_HEIGHT (&pool->video_info)); ++ } ++ } ++ ++ pool->need_copy = FALSE; ++ } else { ++ GstMemory *mem; ++ const guint nstride = pool->port->port_def.format.video.nStride; ++ const guint nslice = pool->port->port_def.format.video.nSliceHeight; ++ gsize offset[GST_VIDEO_MAX_PLANES] = { 0, }; ++ gint stride[GST_VIDEO_MAX_PLANES] = { nstride, 0, }; ++ ++ switch (GST_VIDEO_INFO_FORMAT (&pool->video_info)) { ++ case GST_VIDEO_FORMAT_ABGR: ++ case GST_VIDEO_FORMAT_ARGB: ++ case GST_VIDEO_FORMAT_RGB16: ++ case GST_VIDEO_FORMAT_BGR16: ++ case GST_VIDEO_FORMAT_YUY2: ++ case GST_VIDEO_FORMAT_UYVY: ++ case GST_VIDEO_FORMAT_YVYU: ++ case GST_VIDEO_FORMAT_GRAY8: ++ break; ++ case GST_VIDEO_FORMAT_I420: ++ stride[1] = nstride / 2; ++ offset[1] = offset[0] + stride[0] * nslice; ++ stride[2] = nstride / 2; ++ offset[2] = offset[1] + (stride[1] * nslice / 2); ++ break; ++ case GST_VIDEO_FORMAT_NV12: ++ case GST_VIDEO_FORMAT_NV16: ++ stride[1] = nstride; ++ offset[1] = offset[0] + stride[0] * nslice; ++ break; ++ default: ++ g_assert_not_reached (); ++ break; ++ } ++ ++ if (GST_IS_OMX_VIDEO_DEC (pool->element) && ++ GST_OMX_VIDEO_DEC (pool->element)->use_dmabuf == TRUE && ++ (omx_buf->omx_buf->pOutputPortPrivate)) { ++#if defined (HAVE_MMNGRBUF) && defined (HAVE_VIDEODEC_EXT) ++ if (pool->allocator) ++ gst_object_unref (pool->allocator); ++ pool->allocator = gst_dmabuf_allocator_new (); ++ buf = gst_omx_buffer_pool_create_buffer_contain_dmabuf (pool, ++ omx_buf, (gint *) (&stride), (gsize *) (&offset)); ++ if (!buf) { ++ GST_ERROR_OBJECT (pool, "Can not create buffer contain dmabuf"); ++ return GST_FLOW_ERROR; ++ } ++#else ++ GST_ELEMENT_ERROR (pool->element, STREAM, FAILED, (NULL), ++ ("dmabuf mode is invalid now due to not have MMNGR_BUF or MC does not support getting physical address")); ++ return GST_FLOW_ERROR; ++#endif ++ } else { ++ if (GST_IS_OMX_VIDEO_ENC (pool->element) && ++ pool->port->port_def.eDir == OMX_DirInput) ++ /* Propose actual area of encoder to upstream */ ++ mem = gst_memory_new_wrapped (0, omx_buf->omx_buf->pBuffer, ++ omx_buf->omx_buf->nAllocLen, 0, 0, NULL, NULL); ++ else ++ mem = gst_omx_memory_allocator_alloc (pool->allocator, 0, omx_buf); ++ ++ buf = gst_buffer_new (); ++ gst_buffer_append_memory (buf, mem); ++ g_ptr_array_add (pool->buffers, buf); ++ if (pool->add_videometa) { ++ pool->need_copy = FALSE; ++ } else { ++ GstVideoInfo info; ++ gboolean need_copy = FALSE; ++ gint i; ++ ++ gst_video_info_init (&info); ++ gst_video_info_set_format (&info, ++ GST_VIDEO_INFO_FORMAT (&pool->video_info), ++ GST_VIDEO_INFO_WIDTH (&pool->video_info), ++ GST_VIDEO_INFO_HEIGHT (&pool->video_info)); ++ ++ for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&pool->video_info); i++) { ++ if (info.stride[i] != stride[i] || info.offset[i] != offset[i]) { ++ need_copy = TRUE; ++ break; ++ } ++ } ++ ++ pool->need_copy = need_copy; ++ } ++ ++ if (pool->need_copy || pool->add_videometa) { ++ /* We always add the videometa. It's the job of the user ++ * to copy the buffer if pool->need_copy is TRUE ++ */ ++ gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE, ++ GST_VIDEO_INFO_FORMAT (&pool->video_info), ++ GST_VIDEO_INFO_WIDTH (&pool->video_info), ++ GST_VIDEO_INFO_HEIGHT (&pool->video_info), ++ GST_VIDEO_INFO_N_PLANES (&pool->video_info), offset, stride); ++ } ++ } ++ } ++ ++ gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buf), ++ gst_omx_buffer_data_quark, omx_buf, NULL); ++ ++ *buffer = buf; ++ ++ pool->current_buffer_index++; ++ ++ return GST_FLOW_OK; ++} ++ ++static void ++gst_omx_buffer_pool_free_buffer (GstBufferPool * bpool, GstBuffer * buffer) ++{ ++ GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool); ++ ++ /* If the buffers belong to another pool, restore them now */ ++ GST_OBJECT_LOCK (pool); ++ if (pool->other_pool) { ++ gst_object_replace ((GstObject **) & buffer->pool, ++ (GstObject *) pool->other_pool); ++ } ++ GST_OBJECT_UNLOCK (pool); ++ ++ gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buffer), ++ gst_omx_buffer_data_quark, NULL, NULL); ++ ++ GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->free_buffer (bpool, ++ buffer); ++} ++ ++static GstFlowReturn ++gst_omx_buffer_pool_acquire_buffer (GstBufferPool * bpool, ++ GstBuffer ** buffer, GstBufferPoolAcquireParams * params) ++{ ++ GstFlowReturn ret; ++ GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool); ++ ++ if (pool->port->port_def.eDir == OMX_DirOutput) { ++ GstBuffer *buf; ++ ++ g_return_val_if_fail (pool->current_buffer_index != -1, GST_FLOW_ERROR); ++ ++ buf = g_ptr_array_index (pool->buffers, pool->current_buffer_index); ++ g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); ++ *buffer = buf; ++ ret = GST_FLOW_OK; ++ ++ /* If it's our own memory we have to set the sizes */ ++ if ((!pool->other_pool) && ++ ((GST_OMX_VIDEO_DEC (pool->element)->use_dmabuf) == FALSE)) { ++ GstMemory *mem = gst_buffer_peek_memory (*buffer, 0); ++ ++ g_assert (mem ++ && g_strcmp0 (mem->allocator->mem_type, GST_OMX_MEMORY_TYPE) == 0); ++ mem->size = ((GstOMXMemory *) mem)->buf->omx_buf->nFilledLen; ++ mem->offset = ((GstOMXMemory *) mem)->buf->omx_buf->nOffset; ++ } ++ } else { ++ if (GST_IS_OMX_VIDEO_ENC (pool->element)) { ++ GstBuffer *buf; ++ GstOMXBuffer *omx_buf; ++ gint count = 0; ++ ++ /* Search on number of OMXBuffer of port to find available GstBuffer ++ * (emptied OMXBuffer) to propose to upstream. If after 3 times searching, ++ * can not find target GstBuffer, return flow error ++ */ ++ do { ++ buf = g_ptr_array_index (pool->buffers, pool->enc_buffer_index); ++ g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); ++ ++ omx_buf = ++ gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buf), ++ gst_omx_buffer_data_quark); ++ pool->enc_buffer_index++; ++ if (pool->enc_buffer_index == pool->port->port_def.nBufferCountActual) ++ pool->enc_buffer_index = 0; ++ ++ count += 1; ++ } while (omx_buf->used == TRUE && ++ count < pool->port->port_def.nBufferCountActual * 3); ++ ++ if (count == pool->port->port_def.nBufferCountActual * 3) { ++ ret = GST_FLOW_ERROR; ++ GST_ERROR_OBJECT (pool, ++ "Can not acquire buffer after 3 times searching"); ++ } else { ++ *buffer = buf; ++ ret = GST_FLOW_OK; ++ } ++ } else { ++ /* Acquire any buffer that is available to be filled by upstream */ ++ ret = ++ GST_BUFFER_POOL_CLASS ++ (gst_omx_buffer_pool_parent_class)->acquire_buffer (bpool, buffer, ++ params); ++ } ++ } ++ ++ return ret; ++} ++ ++static void ++gst_omx_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer) ++{ ++ GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool); ++ OMX_ERRORTYPE err; ++ GstOMXBuffer *omx_buf; ++ ++ g_assert (pool->component && pool->port); ++ ++ if (!pool->allocating && !pool->deactivated) { ++ omx_buf = ++ gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buffer), ++ gst_omx_buffer_data_quark); ++ if (pool->port->port_def.eDir == OMX_DirOutput && !omx_buf->used) { ++ /* Release back to the port, can be filled again */ ++ err = gst_omx_port_release_buffer (pool->port, omx_buf); ++ if (err != OMX_ErrorNone) { ++ GST_ELEMENT_ERROR (pool->element, LIBRARY, SETTINGS, (NULL), ++ ("Failed to relase output buffer to component: %s (0x%08x)", ++ gst_omx_error_to_string (err), err)); ++ } ++ } else if (!omx_buf->used) { ++ /* TODO: Implement. ++ * ++ * If not used (i.e. was not passed to the component) this should do ++ * the same as EmptyBufferDone. ++ * If it is used (i.e. was passed to the component) this should do ++ * nothing until EmptyBufferDone. ++ * ++ * EmptyBufferDone should release the buffer to the pool so it can ++ * be allocated again ++ * ++ * Needs something to call back here in EmptyBufferDone, like keeping ++ * a ref on the buffer in GstOMXBuffer until EmptyBufferDone... which ++ * would ensure that the buffer is always unused when this is called. ++ */ ++ if (GST_OMX_VIDEO_ENC (pool->element)->no_copy == FALSE) { ++ g_assert_not_reached (); ++ GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->release_buffer ++ (bpool, buffer); ++ } ++ } ++ } ++} ++ ++static void ++gst_omx_buffer_pool_finalize (GObject * object) ++{ ++ GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (object); ++ ++#ifdef HAVE_MMNGRBUF ++ if (GST_OMX_VIDEO_DEC (pool->element)->use_dmabuf) { ++ gint i; ++ gint dmabuf_id; ++ ++ for (i = 0; i < pool->id_array->len; i++) { ++ dmabuf_id = g_array_index (pool->id_array, gint, i); ++ if (dmabuf_id >= 0) { ++ GST_DEBUG_OBJECT (pool, "mmngr_export_end_in_user (%d)", dmabuf_id); ++ mmngr_export_end_in_user (dmabuf_id); ++ } else { ++ GST_WARNING_OBJECT (pool, "Invalid dmabuf_id"); ++ } ++ } ++ } ++ g_array_free (pool->id_array, TRUE); ++#endif ++ ++ if (pool->element) ++ gst_object_unref (pool->element); ++ pool->element = NULL; ++ ++ if (pool->buffers) ++ g_ptr_array_unref (pool->buffers); ++ pool->buffers = NULL; ++ ++ if (pool->other_pool) ++ gst_object_unref (pool->other_pool); ++ pool->other_pool = NULL; ++ ++ if (pool->allocator) ++ gst_object_unref (pool->allocator); ++ pool->allocator = NULL; ++ ++ if (pool->caps) ++ gst_caps_unref (pool->caps); ++ pool->caps = NULL; ++ ++ G_OBJECT_CLASS (gst_omx_buffer_pool_parent_class)->finalize (object); ++} ++ ++static void ++gst_omx_buffer_pool_class_init (GstOMXBufferPoolClass * klass) ++{ ++ GObjectClass *gobject_class = (GObjectClass *) klass; ++ GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass; ++ ++ gst_omx_buffer_data_quark = g_quark_from_static_string ("GstOMXBufferData"); ++ ++ gobject_class->finalize = gst_omx_buffer_pool_finalize; ++ gstbufferpool_class->start = gst_omx_buffer_pool_start; ++ gstbufferpool_class->stop = gst_omx_buffer_pool_stop; ++ gstbufferpool_class->get_options = gst_omx_buffer_pool_get_options; ++ gstbufferpool_class->set_config = gst_omx_buffer_pool_set_config; ++ gstbufferpool_class->alloc_buffer = gst_omx_buffer_pool_alloc_buffer; ++ gstbufferpool_class->free_buffer = gst_omx_buffer_pool_free_buffer; ++ gstbufferpool_class->acquire_buffer = gst_omx_buffer_pool_acquire_buffer; ++ gstbufferpool_class->release_buffer = gst_omx_buffer_pool_release_buffer; ++} ++ ++static void ++gst_omx_buffer_pool_init (GstOMXBufferPool * pool) ++{ ++ pool->buffers = g_ptr_array_new (); ++ pool->allocator = g_object_new (gst_omx_memory_allocator_get_type (), NULL); ++#ifdef HAVE_MMNGRBUF ++ pool->id_array = g_array_new (FALSE, FALSE, sizeof (gint)); ++#endif ++ pool->enc_buffer_index = 0; ++} ++ ++GstBufferPool * ++gst_omx_buffer_pool_new (GstElement * element, GstOMXComponent * component, ++ GstOMXPort * port) ++{ ++ GstOMXBufferPool *pool; ++ ++ pool = g_object_new (gst_omx_buffer_pool_get_type (), NULL); ++ pool->element = gst_object_ref (element); ++ pool->component = component; ++ pool->port = port; ++ ++ return GST_BUFFER_POOL (pool); ++} +diff --git a/omx/gstomxbufferpool.h b/omx/gstomxbufferpool.h +new file mode 100644 +index 0000000..09cab8d +--- /dev/null ++++ b/omx/gstomxbufferpool.h +@@ -0,0 +1,106 @@ ++/* ++ * Copyright 2014 Advanced Micro Devices, Inc. ++ * Author: Christian König <christian.koenig@amd.com> ++ * Copyright (C) 2015, Renesas Electronics Corporation ++ * ++ * 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_BUFFER_POOL_H__ ++#define __GST_OMX_BUFFER_POOL_H__ ++ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include <gst/gst.h> ++#include <gst/video/gstvideometa.h> ++#include <gst/video/gstvideopool.h> ++ ++#include "gstomx.h" ++ ++G_BEGIN_DECLS ++ ++#define GST_TYPE_OMX_BUFFER_POOL \ ++ (gst_omx_buffer_pool_get_type()) ++#define GST_OMX_BUFFER_POOL(obj) \ ++ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_BUFFER_POOL,GstOMXBufferPool)) ++#define GST_IS_OMX_BUFFER_POOL(obj) \ ++ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_BUFFER_POOL)) ++ ++typedef struct _GstOMXBufferPool GstOMXBufferPool; ++typedef struct _GstOMXBufferPoolClass GstOMXBufferPoolClass; ++ ++struct _GstOMXBufferPool ++{ ++ GstVideoBufferPool parent; ++ ++ GstElement *element; ++ ++ GstCaps *caps; ++ gboolean add_videometa; ++ gboolean need_copy; ++ GstVideoInfo video_info; ++ ++ /* Owned by element, element has to stop this pool before ++ * it destroys component or port */ ++ GstOMXComponent *component; ++ GstOMXPort *port; ++ ++ /* For handling OpenMAX allocated memory */ ++ GstAllocator *allocator; ++ ++ /* Set from outside this pool */ ++ /* TRUE if we're currently allocating all our buffers */ ++ gboolean allocating; ++ /* TRUE if the pool is not used anymore */ ++ gboolean deactivated; ++ ++ /* For populating the pool from another one */ ++ GstBufferPool *other_pool; ++ GPtrArray *buffers; ++ ++ /* Used during acquire for output ports to ++ * specify which buffer has to be retrieved ++ * and during alloc, which buffer has to be ++ * wrapped ++ */ ++ gint current_buffer_index; ++ ++ /* Used during acquire for input port */ ++ gint enc_buffer_index; ++#ifdef HAVE_MMNGRBUF ++ /* Array use to contain dma_id. It is used in export_end dmabuf area */ ++ GArray *id_array; ++#endif ++ ++ /* TRUE if the downstream buffer pool can handle ++ "videosink_buffer_creation_request" query */ ++ gboolean vsink_buf_req_supported; ++}; ++ ++struct _GstOMXBufferPoolClass ++{ ++ GstVideoBufferPoolClass parent_class; ++}; ++ ++GType gst_omx_buffer_pool_get_type (void); ++ ++GstBufferPool *gst_omx_buffer_pool_new (GstElement * element, GstOMXComponent * component, GstOMXPort * port); ++ ++G_END_DECLS ++ ++#endif /* __GST_OMX_BUFFER_POOL_H__ */ +diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c +index 837c623..25b6b30 100644 +--- a/omx/gstomxvideodec.c ++++ b/omx/gstomxvideodec.c +@@ -32,6 +32,7 @@ + #include <unistd.h> /* getpagesize() */ + + #include "gstomxvideodec.h" ++#include "gstomxbufferpool.h" + + #ifdef HAVE_MMNGRBUF + #include "gst/allocators/gstdmabuf.h" +@@ -42,898 +43,6 @@ + GST_DEBUG_CATEGORY_STATIC (gst_omx_video_dec_debug_category); + #define GST_CAT_DEFAULT gst_omx_video_dec_debug_category + +-typedef struct _GstOMXMemory GstOMXMemory; +-typedef struct _GstOMXMemoryAllocator GstOMXMemoryAllocator; +-typedef struct _GstOMXMemoryAllocatorClass GstOMXMemoryAllocatorClass; +- +-struct _GstOMXMemory +-{ +- GstMemory mem; +- +- GstOMXBuffer *buf; +-}; +- +-struct _GstOMXMemoryAllocator +-{ +- GstAllocator parent; +-}; +- +-struct _GstOMXMemoryAllocatorClass +-{ +- GstAllocatorClass parent_class; +-}; +- +-/* User data and function for release OMX buffer in no-copy mode */ +-struct GstOMXBufferCallback +-{ +- GstOMXPort * out_port; +- GstOMXBuffer * buf; +-}; +- +-#define GST_OMX_MEMORY_TYPE "openmax" +-#define DEFAULT_FRAME_PER_SECOND 30 +- +-static GstMemory * +-gst_omx_memory_allocator_alloc_dummy (GstAllocator * allocator, gsize size, +- GstAllocationParams * params) +-{ +- g_assert_not_reached (); +- return NULL; +-} +- +-static void +-gst_omx_memory_allocator_free (GstAllocator * allocator, GstMemory * mem) +-{ +- GstOMXMemory *omem = (GstOMXMemory *) mem; +- +- /* TODO: We need to remember which memories are still used +- * so we can wait until everything is released before allocating +- * new memory +- */ +- +- g_slice_free (GstOMXMemory, omem); +-} +- +-static gpointer +-gst_omx_memory_map (GstMemory * mem, gsize maxsize, GstMapFlags flags) +-{ +- GstOMXMemory *omem = (GstOMXMemory *) mem; +- +- return omem->buf->omx_buf->pBuffer; +-} +- +-static void +-gst_omx_memory_unmap (GstMemory * mem) +-{ +-} +- +-static GstMemory * +-gst_omx_memory_share (GstMemory * mem, gssize offset, gssize size) +-{ +- g_assert_not_reached (); +- return NULL; +-} +- +-GType gst_omx_memory_allocator_get_type (void); +-G_DEFINE_TYPE (GstOMXMemoryAllocator, gst_omx_memory_allocator, +- GST_TYPE_ALLOCATOR); +- +-#define GST_TYPE_OMX_MEMORY_ALLOCATOR (gst_omx_memory_allocator_get_type()) +-#define GST_IS_OMX_MEMORY_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_OMX_MEMORY_ALLOCATOR)) +- +-static void +-gst_omx_memory_allocator_class_init (GstOMXMemoryAllocatorClass * klass) +-{ +- GstAllocatorClass *allocator_class; +- +- allocator_class = (GstAllocatorClass *) klass; +- +- allocator_class->alloc = gst_omx_memory_allocator_alloc_dummy; +- allocator_class->free = gst_omx_memory_allocator_free; +-} +- +-static void +-gst_omx_memory_allocator_init (GstOMXMemoryAllocator * allocator) +-{ +- GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator); +- +- alloc->mem_type = GST_OMX_MEMORY_TYPE; +- alloc->mem_map = gst_omx_memory_map; +- alloc->mem_unmap = gst_omx_memory_unmap; +- alloc->mem_share = gst_omx_memory_share; +- +- /* default copy & is_span */ +- +- GST_OBJECT_FLAG_SET (allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC); +-} +- +-#ifndef HAVE_MMNGRBUF +-static GstMemory * +-gst_omx_memory_allocator_alloc (GstAllocator * allocator, GstMemoryFlags flags, +- GstOMXBuffer * buf, gsize offset, gsize size) +-{ +- GstOMXMemory *mem; +- +- /* FIXME: We don't allow sharing because we need to know +- * when the memory becomes unused and can only then put +- * it back to the pool. Which is done in the pool's release +- * function +- */ +- flags |= GST_MEMORY_FLAG_NO_SHARE; +- +- mem = g_slice_new (GstOMXMemory); +- /* the shared memory is always readonly */ +- gst_memory_init (GST_MEMORY_CAST (mem), flags, allocator, NULL, +- buf->omx_buf->nAllocLen, buf->port->port_def.nBufferAlignment, +- offset, size); +- +- mem->buf = buf; +- +- return GST_MEMORY_CAST (mem); +-} +-#endif +- +-/* Buffer pool for the buffers of an OpenMAX port. +- * +- * This pool is only used if we either passed buffers from another +- * pool to the OMX port or provide the OMX buffers directly to other +- * elements. +- * +- * +- * A buffer is in the pool if it is currently owned by the port, +- * i.e. after OMX_{Fill,Empty}ThisBuffer(). A buffer is outside +- * the pool after it was taken from the port after it was handled +- * by the port, i.e. {Empty,Fill}BufferDone. +- * +- * Buffers can be allocated by us (OMX_AllocateBuffer()) or allocated +- * by someone else and (temporarily) passed to this pool +- * (OMX_UseBuffer(), OMX_UseEGLImage()). In the latter case the pool of +- * the buffer will be overriden, and restored in free_buffer(). Other +- * buffers are just freed there. +- * +- * The pool always has a fixed number of minimum and maximum buffers +- * and these are allocated while starting the pool and released afterwards. +- * They correspond 1:1 to the OMX buffers of the port, which are allocated +- * before the pool is started. +- * +- * Acquiring a buffer from this pool happens after the OMX buffer has +- * been acquired from the port. gst_buffer_pool_acquire_buffer() is +- * supposed to return the buffer that corresponds to the OMX buffer. +- * +- * For buffers provided to upstream, the buffer will be passed to +- * the component manually when it arrives and then unreffed. If the +- * buffer is released before reaching the component it will be just put +- * back into the pool as if EmptyBufferDone has happened. If it was +- * passed to the component, it will be back into the pool when it was +- * released and EmptyBufferDone has happened. +- * +- * For buffers provided to downstream, the buffer will be returned +- * back to the component (OMX_FillThisBuffer()) when it is released. +- */ +- +-static GQuark gst_omx_buffer_data_quark = 0; +- +-#define GST_OMX_BUFFER_POOL(pool) ((GstOMXBufferPool *) pool) +-typedef struct _GstOMXBufferPool GstOMXBufferPool; +-typedef struct _GstOMXBufferPoolClass GstOMXBufferPoolClass; +- +-typedef struct _GstOMXVideoDecBufferData GstOMXVideoDecBufferData; +- +-struct _GstOMXBufferPool +-{ +- GstVideoBufferPool parent; +- +- GstElement *element; +- +- GstCaps *caps; +- gboolean add_videometa; +- GstVideoInfo video_info; +- +- /* Owned by element, element has to stop this pool before +- * it destroys component or port */ +- GstOMXComponent *component; +- GstOMXPort *port; +- +- /* For handling OpenMAX allocated memory */ +- GstAllocator *allocator; +- +- /* Set from outside this pool */ +- /* TRUE if we're currently allocating all our buffers */ +- gboolean allocating; +- +- /* TRUE if the pool is not used anymore */ +- gboolean deactivated; +- +- /* For populating the pool from another one */ +- GstBufferPool *other_pool; +- GPtrArray *buffers; +- +- /* Used during acquire for output ports to +- * specify which buffer has to be retrieved +- * and during alloc, which buffer has to be +- * wrapped +- */ +- gint current_buffer_index; +- +- /* TRUE if the downstream buffer pool can handle +- "videosink_buffer_creation_request" query */ +- gboolean vsink_buf_req_supported; +-}; +- +-struct _GstOMXBufferPoolClass +-{ +- GstVideoBufferPoolClass parent_class; +-}; +- +-struct _GstOMXVideoDecBufferData +-{ +- gboolean already_acquired; +- +-#ifdef HAVE_MMNGRBUF +- gint id_export[GST_VIDEO_MAX_PLANES]; +-#endif +-}; +- +-GType gst_omx_buffer_pool_get_type (void); +- +-G_DEFINE_TYPE (GstOMXBufferPool, gst_omx_buffer_pool, GST_TYPE_BUFFER_POOL); +- +-static void gst_omx_buffer_pool_free_buffer (GstBufferPool * bpool, +- GstBuffer * buffer); +- +-static gboolean +-gst_omx_buffer_pool_start (GstBufferPool * bpool) +-{ +- GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool); +- +- /* Only allow to start the pool if we still are attached +- * to a component and port */ +- GST_OBJECT_LOCK (pool); +- if (!pool->component || !pool->port) { +- GST_OBJECT_UNLOCK (pool); +- return FALSE; +- } +- GST_OBJECT_UNLOCK (pool); +- +- return +- GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->start (bpool); +-} +- +-static gboolean +-gst_omx_buffer_pool_stop (GstBufferPool * bpool) +-{ +- GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool); +- gint i = 0; +- +- /* When not using the default GstBufferPool::GstAtomicQueue then +- * GstBufferPool::free_buffer is not called while stopping the pool +- * (because the queue is empty) */ +- for (i = 0; i < pool->buffers->len; i++) +- GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->release_buffer +- (bpool, g_ptr_array_index (pool->buffers, i)); +- +- /* Remove any buffers that are there */ +- g_ptr_array_set_size (pool->buffers, 0); +- +- if (pool->caps) +- gst_caps_unref (pool->caps); +- pool->caps = NULL; +- +- pool->add_videometa = FALSE; +- +- return GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->stop (bpool); +-} +- +-static const gchar ** +-gst_omx_buffer_pool_get_options (GstBufferPool * bpool) +-{ +- static const gchar *raw_video_options[] = +- { GST_BUFFER_POOL_OPTION_VIDEO_META, NULL }; +- static const gchar *options[] = { NULL }; +- GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool); +- +- GST_OBJECT_LOCK (pool); +- if (pool->port && pool->port->port_def.eDomain == OMX_PortDomainVideo +- && pool->port->port_def.format.video.eCompressionFormat == +- OMX_VIDEO_CodingUnused) { +- GST_OBJECT_UNLOCK (pool); +- return raw_video_options; +- } +- GST_OBJECT_UNLOCK (pool); +- +- return options; +-} +- +-static gboolean +-gst_omx_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config) +-{ +- GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool); +- GstCaps *caps; +- +- GST_OBJECT_LOCK (pool); +- +- if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL)) +- goto wrong_config; +- +- if (caps == NULL) +- goto no_caps; +- +- if (pool->port && pool->port->port_def.eDomain == OMX_PortDomainVideo +- && pool->port->port_def.format.video.eCompressionFormat == +- OMX_VIDEO_CodingUnused) { +- GstVideoInfo info; +- +- /* now parse the caps from the config */ +- if (!gst_video_info_from_caps (&info, caps)) +- goto wrong_video_caps; +- +- /* enable metadata based on config of the pool */ +- pool->add_videometa = +- gst_buffer_pool_config_has_option (config, +- GST_BUFFER_POOL_OPTION_VIDEO_META); +- +- pool->video_info = info; +- } +- +- if (pool->caps) +- gst_caps_unref (pool->caps); +- pool->caps = gst_caps_ref (caps); +- +- GST_OBJECT_UNLOCK (pool); +- +- return GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->set_config +- (bpool, config); +- +- /* ERRORS */ +-wrong_config: +- { +- GST_OBJECT_UNLOCK (pool); +- GST_WARNING_OBJECT (pool, "invalid config"); +- return FALSE; +- } +-no_caps: +- { +- GST_OBJECT_UNLOCK (pool); +- GST_WARNING_OBJECT (pool, "no caps in config"); +- return FALSE; +- } +-wrong_video_caps: +- { +- GST_OBJECT_UNLOCK (pool); +- GST_WARNING_OBJECT (pool, +- "failed getting geometry from caps %" GST_PTR_FORMAT, caps); +- return FALSE; +- } +-} +- +-static GstFlowReturn +-gst_omx_buffer_pool_alloc_buffer (GstBufferPool * bpool, +- GstBuffer ** buffer, GstBufferPoolAcquireParams * params) +-{ +- GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool); +- GstBuffer *buf; +- GstOMXBuffer *omx_buf; +- GstOMXVideoDec *self; +- self = GST_OMX_VIDEO_DEC (pool->element); +- +- g_return_val_if_fail (pool->allocating, GST_FLOW_ERROR); +- +- omx_buf = g_ptr_array_index (pool->port->buffers, pool->current_buffer_index); +- g_return_val_if_fail (omx_buf != NULL, GST_FLOW_ERROR); +- +- if (pool->other_pool) { +- guint i, n; +- +- buf = g_ptr_array_index (pool->buffers, pool->current_buffer_index); +- g_assert (pool->other_pool == buf->pool); +- gst_object_replace ((GstObject **) & buf->pool, NULL); +- +- n = gst_buffer_n_memory (buf); +- for (i = 0; i < n; i++) { +- GstMemory *mem = gst_buffer_peek_memory (buf, i); +- +- /* FIXME: We don't allow sharing because we need to know +- * when the memory becomes unused and can only then put +- * it back to the pool. Which is done in the pool's release +- * function +- */ +- GST_MINI_OBJECT_FLAG_SET (mem, GST_MEMORY_FLAG_NO_SHARE); +- } +- +- if (pool->add_videometa) { +- GstVideoMeta *meta; +- +- meta = gst_buffer_get_video_meta (buf); +- if (!meta) { +- gst_buffer_add_video_meta (buf, GST_VIDEO_FRAME_FLAG_NONE, +- GST_VIDEO_INFO_FORMAT (&pool->video_info), +- GST_VIDEO_INFO_WIDTH (&pool->video_info), +- GST_VIDEO_INFO_HEIGHT (&pool->video_info)); +- } +- } +- } else { +- gsize offset[4] = { 0, }; +- gint stride[4] = { 0, }; +- gsize plane_size[4] = { 0, }; +-#ifndef HAVE_MMNGRBUF +- guint n_planes; +-#endif +- gint i; +- GstOMXVideoDecBufferData *vdbuf_data; +- +- switch (pool->video_info.finfo->format) { +- case GST_VIDEO_FORMAT_I420: +- offset[0] = 0; +- stride[0] = pool->port->port_def.format.video.nStride; +- offset[1] = stride[0] * pool->port->port_def.format.video.nSliceHeight; +- stride[1] = pool->port->port_def.format.video.nStride / 2; +- offset[2] = +- offset[1] + +- stride[1] * (pool->port->port_def.format.video.nSliceHeight / 2); +- stride[2] = pool->port->port_def.format.video.nStride / 2; +- plane_size[0] = pool->port->port_def.format.video.nStride * +- pool->port->port_def.format.video.nFrameHeight; +- plane_size[1] = plane_size[2] = plane_size[0] / 4; +- +-#ifndef HAVE_MMNGRBUF +- n_planes = 3; +-#endif +- break; +- case GST_VIDEO_FORMAT_NV12: +- offset[0] = 0; +- stride[0] = pool->port->port_def.format.video.nStride; +- offset[1] = stride[0] * pool->port->port_def.format.video.nSliceHeight; +- stride[1] = pool->port->port_def.format.video.nStride; +- plane_size[0] = pool->port->port_def.format.video.nStride * +- pool->port->port_def.format.video.nFrameHeight; +- plane_size[1] = plane_size[0] / 2; +- +-#ifndef HAVE_MMNGRBUF +- n_planes = 2; +-#endif +- break; +- default: +- g_assert_not_reached (); +- break; +- } +- +- buf = gst_buffer_new (); +- +-#ifndef HAVE_MMNGRBUF +- if (self->use_dmabuf == FALSE) +- for (i = 0; i < n_planes; i++) +- gst_buffer_append_memory (buf, +- gst_omx_memory_allocator_alloc (pool->allocator, 0, omx_buf, +- offset[i], plane_size[i])); +-#endif +- +- g_ptr_array_add (pool->buffers, buf); +- +- if (pool->add_videometa) +- gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE, +- GST_VIDEO_INFO_FORMAT (&pool->video_info), +- GST_VIDEO_INFO_WIDTH (&pool->video_info), +- GST_VIDEO_INFO_HEIGHT (&pool->video_info), +- GST_VIDEO_INFO_N_PLANES (&pool->video_info), offset, stride); +- +- /* Initialize an already_acquired flag */ +- vdbuf_data = g_slice_new (GstOMXVideoDecBufferData); +- vdbuf_data->already_acquired = FALSE; +-#ifdef HAVE_MMNGRBUF +- if (self->use_dmabuf) +- for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) +- vdbuf_data->id_export[i] = -1; +-#endif +- +- omx_buf->private_data = (void *) vdbuf_data; +- } +- +- gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buf), +- gst_omx_buffer_data_quark, omx_buf, NULL); +- +- *buffer = buf; +- +- pool->current_buffer_index++; +- +- return GST_FLOW_OK; +-} +- +-static void +-gst_omx_buffer_pool_free_buffer (GstBufferPool * bpool, GstBuffer * buffer) +-{ +- GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool); +- GstOMXBuffer *omx_buf; +- GstOMXVideoDec *self; +- self = GST_OMX_VIDEO_DEC (pool->element); +-#ifdef HAVE_MMNGRBUF +- GstOMXVideoDecBufferData *vdbuf_data; +- gint i; +-#endif +- +- /* If the buffers belong to another pool, restore them now */ +- GST_OBJECT_LOCK (pool); +- if (pool->other_pool) { +- gst_object_replace ((GstObject **) & buffer->pool, +- (GstObject *) pool->other_pool); +- } +- GST_OBJECT_UNLOCK (pool); +- +- omx_buf = +- gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buffer), +- gst_omx_buffer_data_quark); +-#ifdef HAVE_MMNGRBUF +- if (self->use_dmabuf) { +- vdbuf_data = (GstOMXVideoDecBufferData *) omx_buf->private_data; +- if (vdbuf_data) { +- for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) +- if (vdbuf_data->id_export[i] >= 0) +- mmngr_export_end_in_user (vdbuf_data->id_export[i]); +- } +- } +-#endif +- g_slice_free (GstOMXVideoDecBufferData, omx_buf->private_data); +- +- gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buffer), +- gst_omx_buffer_data_quark, NULL, NULL); +- +- GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->free_buffer (bpool, +- buffer); +-} +- +-#ifdef HAVE_MMNGRBUF +-static GstBuffer * +-gst_omx_buffer_pool_request_videosink_buffer_creation (GstOMXBufferPool * pool, +- gint dmabuf_fd[GST_VIDEO_MAX_PLANES], gpointer plane_buf[GST_VIDEO_MAX_PLANES], gint stride[GST_VIDEO_MAX_PLANES]) +-{ +- GstQuery *query; +- GValue val = { 0, }; +- GstStructure *structure; +- const GValue *value; +- GstBuffer *buffer; +- GArray *dmabuf_array; +- GArray *stride_array; +- GArray *planebuf_array; +- gint n_planes; +- gint i; +- +- g_value_init (&val, G_TYPE_POINTER); +- g_value_set_pointer (&val, (gpointer) pool->allocator); +- +- dmabuf_array = g_array_new (FALSE, FALSE, sizeof (gint)); +- stride_array = g_array_new (FALSE, FALSE, sizeof (gint)); +- planebuf_array = g_array_new (FALSE, FALSE, sizeof (gpointer)); +- +- n_planes = GST_VIDEO_INFO_N_PLANES (&pool->video_info); +- for (i = 0; i < n_planes; i++) { +- g_array_append_val (dmabuf_array, dmabuf_fd[i]); +- g_array_append_val (stride_array, stride[i]); +- g_array_append_val (planebuf_array, plane_buf[i]); +- } +- +- structure = gst_structure_new ("videosink_buffer_creation_request", +- "width", G_TYPE_INT, pool->port->port_def.format.video.nFrameWidth, +- "height", G_TYPE_INT, pool->port->port_def.format.video.nFrameHeight, +- "stride", G_TYPE_ARRAY, stride_array, +- "dmabuf", G_TYPE_ARRAY, dmabuf_array, +- "planebuf", G_TYPE_ARRAY, planebuf_array, +- "allocator", G_TYPE_POINTER, &val, +- "format", G_TYPE_STRING, +- gst_video_format_to_string (pool->video_info.finfo->format), +- "n_planes", G_TYPE_INT, n_planes, NULL); +- +- query = gst_query_new_custom (GST_QUERY_CUSTOM, structure); +- +- GST_DEBUG_OBJECT (pool, "send a videosink_buffer_creation_request query"); +- +- if (!gst_pad_peer_query (GST_VIDEO_DECODER_SRC_PAD (pool->element), query)) { +- GST_ERROR_OBJECT (pool, "videosink_buffer_creation_request query failed"); +- return NULL; +- } +- +- value = gst_structure_get_value (structure, "buffer"); +- buffer = gst_value_get_buffer (value); +- if (buffer == NULL) { +- GST_ERROR_OBJECT (pool, +- "could not get a buffer from videosink_buffer_creation query"); +- return NULL; +- } +- +- gst_query_unref (query); +- +- g_array_free (dmabuf_array, TRUE); +- g_array_free (stride_array, TRUE); +- +- return buffer; +-} +-#endif +- +-#ifdef HAVE_MMNGRBUF +-static gboolean +-gst_omx_buffer_pool_export_dmabuf (GstOMXBufferPool * pool, +- guint phys_addr, gint size, gint boundary, gint * id_export, +- gint * dmabuf_fd) +-{ +- gint res; +- +- res = +- mmngr_export_start_in_user (id_export, +- (size + boundary - 1) & ~(boundary - 1), (unsigned long) phys_addr, +- dmabuf_fd); +- if (res != R_MM_OK) { +- GST_ERROR_OBJECT (pool, +- "mmngr_export_start_in_user failed (phys_addr:0x%08x)", phys_addr); +- return FALSE; +- } +- GST_DEBUG_OBJECT (pool, +- "Export dmabuf:%d id_export:%d (phys_addr:0x%08x)", *dmabuf_fd, +- *id_export, phys_addr); +- +- return TRUE; +-} +-#endif +- +-static GstFlowReturn +-gst_omx_buffer_pool_acquire_buffer (GstBufferPool * bpool, +- GstBuffer ** buffer, GstBufferPoolAcquireParams * params) +-{ +- GstFlowReturn ret; +- GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool); +- GstOMXVideoDec *self; +- self = GST_OMX_VIDEO_DEC (pool->element); +- +- if (pool->port->port_def.eDir == OMX_DirOutput) { +- GstBuffer *buf; +- GstOMXBuffer *omx_buf; +- GstOMXVideoDecBufferData *vdbuf_data; +-#ifdef HAVE_MMNGRBUF +- guint n_mem; +-#endif +- +- g_return_val_if_fail (pool->current_buffer_index != -1, GST_FLOW_ERROR); +- +- buf = g_ptr_array_index (pool->buffers, pool->current_buffer_index); +- g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); +- +- omx_buf = +- gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buf), +- gst_omx_buffer_data_quark); +- +- vdbuf_data = (GstOMXVideoDecBufferData *) omx_buf->private_data; +-#ifdef HAVE_MMNGRBUF +- if (self->use_dmabuf) +- { +- n_mem = gst_buffer_n_memory (buf); +- if (n_mem == 0) { +- GstBuffer *new_buf; +- GstVideoMeta *vmeta; +- gint n_planes; +- gint i; +- gint dmabuf_fd[GST_VIDEO_MAX_PLANES]; +- gint plane_size[GST_VIDEO_MAX_PLANES]; +- gpointer plane_buf[GST_VIDEO_MAX_PLANES]; +- guint phys_addr; +- OMXR_MC_VIDEO_DECODERESULTTYPE *decode_res = +- (OMXR_MC_VIDEO_DECODERESULTTYPE *) omx_buf-> +- omx_buf->pOutputPortPrivate; +- gint page_size; +- +- GST_DEBUG_OBJECT (pool, "Create dmabuf mem pBuffer=%p", +- omx_buf->omx_buf->pBuffer); +- +- vmeta = gst_buffer_get_video_meta (buf); +- +- phys_addr = (guint) decode_res->pvPhysImageAddressY; +- page_size = getpagesize (); +- +- /* Export a dmabuf file descriptor from the head of Y plane to +- * the end of the buffer so that mapping the whole plane as +- * contiguous memory is available. */ +- if (!gst_omx_buffer_pool_export_dmabuf (pool, phys_addr, +- pool->port->port_def.nBufferSize, page_size, +- &vdbuf_data->id_export[0], &dmabuf_fd[0])) { +- GST_ERROR_OBJECT (pool, "dmabuf exporting failed"); +- return GST_FLOW_ERROR; +- } +- +- plane_size[0] = vmeta->stride[0] * +- GST_VIDEO_INFO_COMP_HEIGHT (&pool->video_info, 0); +- plane_buf[0] = omx_buf->omx_buf->pBuffer; +- +- /* Export dmabuf file descriptors from second and subsequent planes */ +- n_planes = GST_VIDEO_INFO_N_PLANES (&pool->video_info); +- for (i = 1; i < n_planes; i++) { +- phys_addr = (guint) decode_res->pvPhysImageAddressY + vmeta->offset[i]; +- plane_size[i] = vmeta->stride[i] * +- GST_VIDEO_INFO_COMP_HEIGHT (&pool->video_info, i); +- plane_buf[i] = omx_buf->omx_buf->pBuffer + vmeta->offset[i]; +- +- if (!gst_omx_buffer_pool_export_dmabuf (pool, phys_addr, plane_size[i], +- page_size, &vdbuf_data->id_export[i], &dmabuf_fd[i])) { +- GST_ERROR_OBJECT (pool, "dmabuf exporting failed"); +- return GST_FLOW_ERROR; +- } +- } +- +- if (pool->vsink_buf_req_supported) +- new_buf = gst_omx_buffer_pool_request_videosink_buffer_creation (pool, +- dmabuf_fd, plane_buf, vmeta->stride); +- else { +- GstVideoMeta *new_meta; +- +- new_buf = gst_buffer_new (); +- for (i = 0; i < n_planes; i++) +- gst_buffer_append_memory (new_buf, +- gst_dmabuf_allocator_alloc (pool->allocator, dmabuf_fd[i], +- plane_size[i])); +- +- gst_buffer_add_video_meta_full (new_buf, GST_VIDEO_FRAME_FLAG_NONE, +- GST_VIDEO_INFO_FORMAT (&pool->video_info), +- GST_VIDEO_INFO_WIDTH (&pool->video_info), +- GST_VIDEO_INFO_HEIGHT (&pool->video_info), +- GST_VIDEO_INFO_N_PLANES (&pool->video_info), vmeta->offset, +- vmeta->stride); +- +- new_meta = gst_buffer_get_video_meta (new_buf); +- /* To avoid detaching meta data when a buffer returns +- to the buffer pool */ +- GST_META_FLAG_SET (new_meta, GST_META_FLAG_POOLED); +- } +- +- g_ptr_array_remove_index (pool->buffers, pool->current_buffer_index); +- +- gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buf), +- gst_omx_buffer_data_quark, NULL, NULL); +- +- gst_buffer_unref (buf); +- +- gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (new_buf), +- gst_omx_buffer_data_quark, omx_buf, NULL); +- +- g_ptr_array_add (pool->buffers, new_buf); +- +- *buffer = new_buf; +- } else +- *buffer = buf; +- } else +-#endif +- *buffer = buf; +- +- vdbuf_data->already_acquired = TRUE; +- +- ret = GST_FLOW_OK; +- } else { +- /* Acquire any buffer that is available to be filled by upstream */ +- ret = +- GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->acquire_buffer +- (bpool, buffer, params); +- } +- +- return ret; +-} +- +-static void +-gst_omx_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer) +-{ +- GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (bpool); +- OMX_ERRORTYPE err; +- GstOMXBuffer *omx_buf; +- +- g_assert (pool->component && pool->port); +- +- if (pool->allocating && !pool->deactivated) { +- GstOMXVideoDecBufferData *vdbuf_data; +- +- omx_buf = +- gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buffer), +- gst_omx_buffer_data_quark); +- +- vdbuf_data = (GstOMXVideoDecBufferData *) omx_buf->private_data; +- +- if (pool->port->port_def.eDir == OMX_DirOutput && !omx_buf->used && +- vdbuf_data->already_acquired) { +- /* Release back to the port, can be filled again */ +- err = gst_omx_port_release_buffer (pool->port, omx_buf); +- if (err != OMX_ErrorNone) { +- GST_ELEMENT_ERROR (pool->element, LIBRARY, SETTINGS, (NULL), +- ("Failed to relase output buffer to component: %s (0x%08x)", +- gst_omx_error_to_string (err), err)); +- } +- vdbuf_data->already_acquired = FALSE; +- } else if (pool->port->port_def.eDir == OMX_DirInput && !omx_buf->used) { +- /* TODO: Implement. +- * +- * If not used (i.e. was not passed to the component) this should do +- * the same as EmptyBufferDone. +- * If it is used (i.e. was passed to the component) this should do +- * nothing until EmptyBufferDone. +- * +- * EmptyBufferDone should release the buffer to the pool so it can +- * be allocated again +- * +- * Needs something to call back here in EmptyBufferDone, like keeping +- * a ref on the buffer in GstOMXBuffer until EmptyBufferDone... which +- * would ensure that the buffer is always unused when this is called. +- */ +- g_assert_not_reached (); +- GST_BUFFER_POOL_CLASS (gst_omx_buffer_pool_parent_class)->release_buffer +- (bpool, buffer); +- } +- } +-} +- +-static void +-gst_omx_buffer_pool_finalize (GObject * object) +-{ +- GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (object); +- +- if (pool->element) +- gst_object_unref (pool->element); +- pool->element = NULL; +- +- if (pool->buffers) +- g_ptr_array_unref (pool->buffers); +- pool->buffers = NULL; +- +- if (pool->other_pool) +- gst_object_unref (pool->other_pool); +- pool->other_pool = NULL; +- +- if (pool->allocator) +- gst_object_unref (pool->allocator); +- pool->allocator = NULL; +- +- if (pool->caps) +- gst_caps_unref (pool->caps); +- pool->caps = NULL; +- +- G_OBJECT_CLASS (gst_omx_buffer_pool_parent_class)->finalize (object); +-} +- +-static void +-gst_omx_buffer_pool_class_init (GstOMXBufferPoolClass * klass) +-{ +- GObjectClass *gobject_class = (GObjectClass *) klass; +- GstBufferPoolClass *gstbufferpool_class = (GstBufferPoolClass *) klass; +- +- gst_omx_buffer_data_quark = g_quark_from_static_string ("GstOMXBufferData"); +- +- gobject_class->finalize = gst_omx_buffer_pool_finalize; +- gstbufferpool_class->start = gst_omx_buffer_pool_start; +- gstbufferpool_class->stop = gst_omx_buffer_pool_stop; +- gstbufferpool_class->get_options = gst_omx_buffer_pool_get_options; +- gstbufferpool_class->set_config = gst_omx_buffer_pool_set_config; +- gstbufferpool_class->alloc_buffer = gst_omx_buffer_pool_alloc_buffer; +- gstbufferpool_class->free_buffer = gst_omx_buffer_pool_free_buffer; +- gstbufferpool_class->acquire_buffer = gst_omx_buffer_pool_acquire_buffer; +- gstbufferpool_class->release_buffer = gst_omx_buffer_pool_release_buffer; +-} +- +-static void +-gst_omx_buffer_pool_init (GstOMXBufferPool * pool) +-{ +- pool->buffers = g_ptr_array_new (); +-#ifdef HAVE_MMNGRBUF +- pool->allocator = gst_dmabuf_allocator_new (); +-#else +- pool->allocator = g_object_new (gst_omx_memory_allocator_get_type (), NULL); +-#endif +-} +- +-static GstBufferPool * +-gst_omx_buffer_pool_new (GstElement * element, GstOMXComponent * component, +- GstOMXPort * port) +-{ +- GstOMXBufferPool *pool; +- +- pool = g_object_new (gst_omx_buffer_pool_get_type (), NULL); +- pool->element = gst_object_ref (element); +- pool->component = component; +- pool->port = port; +- pool->vsink_buf_req_supported = FALSE; +- +- return GST_BUFFER_POOL (pool); +-} +- + typedef struct _BufferIdentification BufferIdentification; + struct _BufferIdentification + { +@@ -979,8 +88,9 @@ static void gst_omx_video_dec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); + static void gst_omx_video_dec_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); ++/* + static void GstOMXBufCallbackfunc (struct GstOMXBufferCallback *); +- ++*/ + enum + { + PROP_0, +@@ -999,6 +109,9 @@ enum + G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstOMXVideoDec, gst_omx_video_dec, + GST_TYPE_VIDEO_DECODER, DEBUG_INIT); + ++/* Default fps for input files that does not support fps */ ++#define DEFAULT_FRAME_PER_SECOND 30 ++ + static gsize + gst_omx_video_dec_copy_frame (GstOMXVideoDec * self, GstBuffer * inbuf, + guint offset, GstOMXBuffer * outbuf) +@@ -1691,6 +804,7 @@ gst_omx_video_dec_deallocate_output_buffers (GstOMXVideoDec * self) + return err; + } + ++/* + static void GstOMXBufCallbackfunc (struct GstOMXBufferCallback *release) + { + if (!release) +@@ -1702,6 +816,7 @@ static void GstOMXBufCallbackfunc (struct GstOMXBufferCallback *release) + + g_free (release); + } ++*/ + + static GstBuffer * + gst_omx_video_dec_create_buffer_from_omx_output (GstOMXVideoDec * self, +@@ -1762,7 +877,7 @@ gst_omx_video_dec_create_buffer_from_omx_output (GstOMXVideoDec * self, + GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (vinfo->finfo, i, sliceheigh); + used_size = stride[i] * + GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (vinfo->finfo, i, height); +- ++#if 0 + if (i == 0) { + struct GstOMXBufferCallback *release; + release = g_malloc (sizeof(struct GstOMXBufferCallback)); +@@ -1774,6 +889,7 @@ gst_omx_video_dec_create_buffer_from_omx_output (GstOMXVideoDec * self, + plane_size, 0, used_size, release, GstOMXBufCallbackfunc); + } + else ++#endif + /* Only release OMX buffer one time. Do not add callback + * function to other planes + * (These planes are from same OMX buffer) */ +@@ -2042,15 +1158,7 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self) + + n = port->buffers->len; + for (i = 0; i < n; i++) { +- GstBuffer *outbuf; +- GstOMXBuffer *tmp; +- +- outbuf = +- g_ptr_array_index (GST_OMX_BUFFER_POOL (self-> +- out_port_pool)->buffers, i); +- tmp = +- gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (outbuf), +- gst_omx_buffer_data_quark); ++ GstOMXBuffer *tmp = g_ptr_array_index (port->buffers, i); + + if (tmp == buf) + break; +@@ -2084,15 +1192,7 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self) + + n = port->buffers->len; + for (i = 0; i < n; i++) { +- GstBuffer *outbuf; +- GstOMXBuffer *tmp; +- +- outbuf = +- g_ptr_array_index (GST_OMX_BUFFER_POOL (self-> +- out_port_pool)->buffers, i); +- tmp = +- gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (outbuf), +- gst_omx_buffer_data_quark); ++ GstOMXBuffer *tmp = g_ptr_array_index (port->buffers, i); + + if (tmp == buf) + break; +diff --git a/omx/gstomxvideoenc.c b/omx/gstomxvideoenc.c +index cec44cb..b36c46e 100644 +--- a/omx/gstomxvideoenc.c ++++ b/omx/gstomxvideoenc.c +@@ -28,6 +28,11 @@ + #include <string.h> + + #include "gstomxvideoenc.h" ++#include "gstomxbufferpool.h" ++#ifdef HAVE_MMNGRBUF ++#include "mmngr_buf_user_public.h" ++#endif ++#include "gst/allocators/gstdmabuf.h" + + GST_DEBUG_CATEGORY_STATIC (gst_omx_video_enc_debug_category); + #define GST_CAT_DEFAULT gst_omx_video_enc_debug_category +@@ -68,6 +73,13 @@ buffer_identification_free (BufferIdentification * id) + g_slice_free (BufferIdentification, id); + } + ++/* Used in dmabuf mode */ ++struct _GstOMXVideoEncPrivate ++{ ++ /* Array contain id when using mmngrbuf to import fd */ ++ GArray *id_array; ++}; ++ + /* prototypes */ + static void gst_omx_video_enc_finalize (GObject * object); + static void gst_omx_video_enc_set_property (GObject * object, guint prop_id, +@@ -109,7 +121,8 @@ enum + PROP_TARGET_BITRATE, + PROP_QUANT_I_FRAMES, + PROP_QUANT_P_FRAMES, +- PROP_QUANT_B_FRAMES ++ PROP_QUANT_B_FRAMES, ++ PROP_NO_COPY + }; + + /* FIXME: Better defaults */ +@@ -175,6 +188,11 @@ gst_omx_video_enc_class_init (GstOMXVideoEncClass * klass) + 0, G_MAXUINT, GST_OMX_VIDEO_ENC_QUANT_B_FRAMES_DEFAULT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_READY)); ++ g_object_class_install_property (gobject_class, PROP_NO_COPY, ++ g_param_spec_boolean ("no-copy", "Propose buffer to upstream", ++ "Whether or not to use no copy method", ++ FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | ++ GST_PARAM_MUTABLE_READY)); + + element_class->change_state = + GST_DEBUG_FUNCPTR (gst_omx_video_enc_change_state); +@@ -210,7 +228,11 @@ gst_omx_video_enc_init (GstOMXVideoEnc * self) + self->quant_i_frames = GST_OMX_VIDEO_ENC_QUANT_I_FRAMES_DEFAULT; + self->quant_p_frames = GST_OMX_VIDEO_ENC_QUANT_P_FRAMES_DEFAULT; + self->quant_b_frames = GST_OMX_VIDEO_ENC_QUANT_B_FRAMES_DEFAULT; +- ++ self->no_copy = TRUE; ++ self->priv = ++ G_TYPE_INSTANCE_GET_PRIVATE (self, GST_TYPE_OMX_VIDEO_ENC, ++ GstOMXVideoEncPrivate); ++ self->priv->id_array = g_array_new (FALSE, FALSE, sizeof (gint)); + g_mutex_init (&self->drain_lock); + g_cond_init (&self->drain_cond); + } +@@ -413,6 +435,16 @@ gst_omx_video_enc_finalize (GObject * object) + g_mutex_clear (&self->drain_lock); + g_cond_clear (&self->drain_cond); + ++#ifdef HAVE_MMNGRBUF ++ if (self->priv->id_array->len > 0) { ++ gint i; ++ for (i = 0; i < self->priv->id_array->len; i++) ++ mmngr_import_end_in_user (g_array_index (self->priv->id_array, gint, ++ i)); ++ } ++#endif; ++ g_array_free (self->priv->id_array, TRUE); ++ + G_OBJECT_CLASS (gst_omx_video_enc_parent_class)->finalize (object); + } + +@@ -453,6 +485,9 @@ gst_omx_video_enc_set_property (GObject * object, guint prop_id, + case PROP_QUANT_B_FRAMES: + self->quant_b_frames = g_value_get_uint (value); + break; ++ case PROP_NO_COPY: ++ self->no_copy = g_value_get_boolean (value); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -481,6 +516,9 @@ gst_omx_video_enc_get_property (GObject * object, guint prop_id, GValue * value, + case PROP_QUANT_B_FRAMES: + g_value_set_uint (value, self->quant_b_frames); + break; ++ case PROP_NO_COPY: ++ g_value_set_boolean (value, self->no_copy); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -1125,163 +1163,168 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder, + GST_DEBUG_OBJECT (self, "Setting new format %s", + gst_video_format_to_string (info->finfo->format)); + +- gst_omx_port_get_port_definition (self->enc_in_port, &port_def); +- +- needs_disable = +- gst_omx_component_get_state (self->enc, +- GST_CLOCK_TIME_NONE) != OMX_StateLoaded; +- /* If the component is not in Loaded state and a real format change happens +- * we have to disable the port and re-allocate all buffers. If no real +- * format change happened we can just exit here. ++ /* If there is inport pool, it means that OMXBuffer has already allocated on ++ * propose_allocation. Do not allocate OMXBuffer on set_format + */ +- if (needs_disable) { +- GST_DEBUG_OBJECT (self, "Need to disable and drain encoder"); +- gst_omx_video_enc_drain (self, FALSE); +- gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE); +- +- /* Wait until the srcpad loop is finished, +- * unlock GST_VIDEO_ENCODER_STREAM_LOCK to prevent deadlocks +- * caused by using this lock from inside the loop function */ +- GST_VIDEO_ENCODER_STREAM_UNLOCK (self); +- gst_pad_stop_task (GST_VIDEO_ENCODER_SRC_PAD (encoder)); +- GST_VIDEO_ENCODER_STREAM_LOCK (self); +- +- if (gst_omx_port_set_enabled (self->enc_in_port, FALSE) != OMX_ErrorNone) +- return FALSE; +- if (gst_omx_port_set_enabled (self->enc_out_port, FALSE) != OMX_ErrorNone) +- return FALSE; +- if (gst_omx_port_wait_buffers_released (self->enc_in_port, +- 5 * GST_SECOND) != OMX_ErrorNone) +- return FALSE; +- if (gst_omx_port_wait_buffers_released (self->enc_out_port, +- 1 * GST_SECOND) != OMX_ErrorNone) +- return FALSE; +- if (gst_omx_port_deallocate_buffers (self->enc_in_port) != OMX_ErrorNone) +- return FALSE; +- if (gst_omx_port_deallocate_buffers (self->enc_out_port) != OMX_ErrorNone) +- return FALSE; +- if (gst_omx_port_wait_enabled (self->enc_in_port, +- 1 * GST_SECOND) != OMX_ErrorNone) +- return FALSE; +- if (gst_omx_port_wait_enabled (self->enc_out_port, +- 1 * GST_SECOND) != OMX_ErrorNone) +- return FALSE; +- +- GST_DEBUG_OBJECT (self, "Encoder drained and disabled"); +- } ++ if (!self->in_port_pool) { ++ gst_omx_port_get_port_definition (self->enc_in_port, &port_def); ++ ++ needs_disable = ++ gst_omx_component_get_state (self->enc, ++ GST_CLOCK_TIME_NONE) != OMX_StateLoaded; ++ /* If the component is not in Loaded state and a real format change happens ++ * we have to disable the port and re-allocate all buffers. If no real ++ * format change happened we can just exit here. ++ */ ++ if (needs_disable) { ++ GST_DEBUG_OBJECT (self, "Need to disable and drain encoder"); ++ gst_omx_video_enc_drain (self, FALSE); ++ gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE); ++ ++ /* Wait until the srcpad loop is finished, ++ * unlock GST_VIDEO_ENCODER_STREAM_LOCK to prevent deadlocks ++ * caused by using this lock from inside the loop function */ ++ GST_VIDEO_ENCODER_STREAM_UNLOCK (self); ++ gst_pad_stop_task (GST_VIDEO_ENCODER_SRC_PAD (encoder)); ++ GST_VIDEO_ENCODER_STREAM_LOCK (self); + +- negotiation_map = gst_omx_video_enc_get_supported_colorformats (self); +- if (!negotiation_map) { +- /* Fallback */ +- switch (info->finfo->format) { +- case GST_VIDEO_FORMAT_I420: +- port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; +- break; +- case GST_VIDEO_FORMAT_NV16: +- case GST_VIDEO_FORMAT_NV12: +- port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; +- break; +- default: +- GST_ERROR_OBJECT (self, "Unsupported format %s", +- gst_video_format_to_string (info->finfo->format)); ++ if (gst_omx_port_set_enabled (self->enc_in_port, FALSE) != OMX_ErrorNone) + return FALSE; +- break; ++ if (gst_omx_port_set_enabled (self->enc_out_port, FALSE) != OMX_ErrorNone) ++ return FALSE; ++ if (gst_omx_port_wait_buffers_released (self->enc_in_port, ++ 5 * GST_SECOND) != OMX_ErrorNone) ++ return FALSE; ++ if (gst_omx_port_wait_buffers_released (self->enc_out_port, ++ 1 * GST_SECOND) != OMX_ErrorNone) ++ return FALSE; ++ if (gst_omx_port_deallocate_buffers (self->enc_in_port) != OMX_ErrorNone) ++ return FALSE; ++ if (gst_omx_port_deallocate_buffers (self->enc_out_port) != OMX_ErrorNone) ++ return FALSE; ++ if (gst_omx_port_wait_enabled (self->enc_in_port, ++ 1 * GST_SECOND) != OMX_ErrorNone) ++ return FALSE; ++ if (gst_omx_port_wait_enabled (self->enc_out_port, ++ 1 * GST_SECOND) != OMX_ErrorNone) ++ return FALSE; ++ ++ GST_DEBUG_OBJECT (self, "Encoder drained and disabled"); + } +- } else { +- for (l = negotiation_map; l; l = l->next) { +- VideoNegotiationMap *m = l->data; + +- if (m->format == info->finfo->format) { +- port_def.format.video.eColorFormat = m->type; +- break; ++ negotiation_map = gst_omx_video_enc_get_supported_colorformats (self); ++ if (!negotiation_map) { ++ /* Fallback */ ++ switch (info->finfo->format) { ++ case GST_VIDEO_FORMAT_I420: ++ port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; ++ break; ++ case GST_VIDEO_FORMAT_NV16: ++ case GST_VIDEO_FORMAT_NV12: ++ port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; ++ break; ++ default: ++ GST_ERROR_OBJECT (self, "Unsupported format %s", ++ gst_video_format_to_string (info->finfo->format)); ++ return FALSE; ++ break; ++ } ++ } else { ++ for (l = negotiation_map; l; l = l->next) { ++ VideoNegotiationMap *m = l->data; ++ ++ if (m->format == info->finfo->format) { ++ port_def.format.video.eColorFormat = m->type; ++ break; ++ } + } ++ g_list_free_full (negotiation_map, ++ (GDestroyNotify) video_negotiation_map_free); + } +- g_list_free_full (negotiation_map, +- (GDestroyNotify) video_negotiation_map_free); +- } + +- port_def.format.video.nFrameWidth = info->width; +- if (port_def.nBufferAlignment) +- port_def.format.video.nStride = +- (info->width + port_def.nBufferAlignment - 1) & +- (~(port_def.nBufferAlignment - 1)); +- else +- { +- if (klass->cdata.hacks & GST_OMX_HACK_RENESAS_ENCMC_STRIDE_ALIGN) ++ port_def.format.video.nFrameWidth = info->width; ++ if (port_def.nBufferAlignment) ++ port_def.format.video.nStride = ++ (info->width + port_def.nBufferAlignment - 1) & ++ (~(port_def.nBufferAlignment - 1)); ++ else + { +- switch (port_def.format.video.eColorFormat) { +- case OMX_COLOR_FormatYUV420Planar: { +- /*Renesas encode MC only support following strides*/ +- if (info->width <= 256) +- port_def.format.video.nStride = 256; +- else if ((info->width > 256) && (info->width <= 512)) +- port_def.format.video.nStride = 512; +- else if ((info->width > 512) && (info->width <= 1024)) +- port_def.format.video.nStride = 1024; +- else +- port_def.format.video.nStride = 2048; ++ if (klass->cdata.hacks & GST_OMX_HACK_RENESAS_ENCMC_STRIDE_ALIGN) ++ { ++ switch (port_def.format.video.eColorFormat) { ++ case OMX_COLOR_FormatYUV420Planar: { ++ /*Renesas encode MC only support following strides*/ ++ if (info->width <= 256) ++ port_def.format.video.nStride = 256; ++ else if ((info->width > 256) && (info->width <= 512)) ++ port_def.format.video.nStride = 512; ++ else if ((info->width > 512) && (info->width <= 1024)) ++ port_def.format.video.nStride = 1024; ++ else ++ port_def.format.video.nStride = 2048; ++ break; ++ } ++ case OMX_COLOR_FormatYUV420SemiPlanar: ++ port_def.format.video.nStride = ((info->width + 127) & ~ 127); /* Align 128 */ + break; +- } +- case OMX_COLOR_FormatYUV420SemiPlanar: +- port_def.format.video.nStride = ((info->width + 127) & ~ 127); /* Align 128 */ +- break; +- default: ++ default: ++ port_def.format.video.nStride = GST_ROUND_UP_4 (info->width); /* Safe (?) default */ ++ break; ++ } ++ } else { + port_def.format.video.nStride = GST_ROUND_UP_4 (info->width); /* Safe (?) default */ +- break; + } +- } else { +- port_def.format.video.nStride = GST_ROUND_UP_4 (info->width); /* Safe (?) default */ + } +- } + +- port_def.format.video.nFrameHeight = info->height; +- port_def.format.video.nSliceHeight = info->height; ++ port_def.format.video.nFrameHeight = info->height; ++ port_def.format.video.nSliceHeight = info->height; + +- switch (port_def.format.video.eColorFormat) { +- case OMX_COLOR_FormatYUV420Planar: +- case OMX_COLOR_FormatYUV420PackedPlanar: +- port_def.nBufferSize = +- (port_def.format.video.nStride * port_def.format.video.nFrameHeight) + +- 2 * ((port_def.format.video.nStride / 2) * +- ((port_def.format.video.nFrameHeight + 1) / 2)); +- break; +- +- case OMX_COLOR_FormatYUV420SemiPlanar: +- port_def.nBufferSize = +- (port_def.format.video.nStride * port_def.format.video.nFrameHeight) + +- (port_def.format.video.nStride * +- ((port_def.format.video.nFrameHeight + 1) / 2)); +- break; ++ switch (port_def.format.video.eColorFormat) { ++ case OMX_COLOR_FormatYUV420Planar: ++ case OMX_COLOR_FormatYUV420PackedPlanar: ++ port_def.nBufferSize = ++ (port_def.format.video.nStride * port_def.format.video.nFrameHeight) + ++ 2 * ((port_def.format.video.nStride / 2) * ++ ((port_def.format.video.nFrameHeight + 1) / 2)); ++ break; + +- default: +- g_assert_not_reached (); +- } ++ case OMX_COLOR_FormatYUV420SemiPlanar: ++ port_def.nBufferSize = ++ (port_def.format.video.nStride * port_def.format.video.nFrameHeight) + ++ (port_def.format.video.nStride * ++ ((port_def.format.video.nFrameHeight + 1) / 2)); ++ break; + +- if (info->fps_n == 0) { +- port_def.format.video.xFramerate = 0; +- } else { +- if (!(klass->cdata.hacks & GST_OMX_HACK_VIDEO_FRAMERATE_INTEGER)) +- port_def.format.video.xFramerate = (info->fps_n << 16) / (info->fps_d); +- else +- port_def.format.video.xFramerate = (info->fps_n) / (info->fps_d); +- } ++ default: ++ g_assert_not_reached (); ++ } + +- GST_DEBUG_OBJECT (self, "Setting inport port definition"); +- if (gst_omx_port_update_port_definition (self->enc_in_port, +- &port_def) != OMX_ErrorNone) +- return FALSE; ++ if (info->fps_n == 0) { ++ port_def.format.video.xFramerate = 0; ++ } else { ++ if (!(klass->cdata.hacks & GST_OMX_HACK_VIDEO_FRAMERATE_INTEGER)) ++ port_def.format.video.xFramerate = (info->fps_n << 16) / (info->fps_d); ++ else ++ port_def.format.video.xFramerate = (info->fps_n) / (info->fps_d); ++ } + +- if (klass->set_format) { +- if (!klass->set_format (self, self->enc_in_port, state)) { +- GST_ERROR_OBJECT (self, "Subclass failed to set the new format"); ++ GST_DEBUG_OBJECT (self, "Setting inport port definition"); ++ if (gst_omx_port_update_port_definition (self->enc_in_port, ++ &port_def) != OMX_ErrorNone) + return FALSE; ++ ++ if (klass->set_format) { ++ if (!klass->set_format (self, self->enc_in_port, state)) { ++ GST_ERROR_OBJECT (self, "Subclass failed to set the new format"); ++ return FALSE; ++ } + } +- } + +- GST_DEBUG_OBJECT (self, "Updating outport port definition"); +- if (gst_omx_port_update_port_definition (self->enc_out_port, +- NULL) != OMX_ErrorNone) +- return FALSE; ++ GST_DEBUG_OBJECT (self, "Updating outport port definition"); ++ if (gst_omx_port_update_port_definition (self->enc_out_port, ++ NULL) != OMX_ErrorNone) ++ return FALSE; ++ } + + GST_DEBUG_OBJECT (self, "Enabling component"); + if (needs_disable) { +@@ -1299,11 +1342,13 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder, + return FALSE; + + /* Need to allocate buffers to reach Idle state */ +- if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone) +- return FALSE; ++ if (!self->in_port_pool) { ++ if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone) ++ return FALSE; ++ } + + /* Allocate for output port */ +- if (gst_omx_port_allocate_buffers (self->enc_out_port) != OMX_ErrorNone) ++ if (gst_omx_port_allocate_buffers (self->enc_out_port) != OMX_ErrorNone) + return FALSE; + if (gst_omx_component_get_state (self->enc, + GST_CLOCK_TIME_NONE) != OMX_StateIdle) +@@ -1349,7 +1394,9 @@ gst_omx_video_enc_reset (GstVideoEncoder * encoder, gboolean hard) + + self = GST_OMX_VIDEO_ENC (encoder); + +- GST_DEBUG_OBJECT (self, "Resetting encoder"); ++ GST_DEBUG_OBJECT (self, "Resetting encoder %s", hard ? "(hard)" : ""); ++ ++ return TRUE; + + gst_omx_port_set_flushing (self->enc_in_port, 5 * GST_SECOND, TRUE); + gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE); +@@ -1739,11 +1786,50 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder, + gst_omx_error_to_string (err), err); + } + +- /* Copy the buffer content in chunks of size as requested +- * by the port */ +- if (!gst_omx_video_enc_fill_buffer (self, frame->input_buffer, buf)) { +- gst_omx_port_release_buffer (port, buf); +- goto buffer_fill_error; ++ if (self->in_port_pool) { ++ GstMapInfo in_info; ++ gint count = 0; ++ GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (self->in_port_pool); ++ ++ /* Compare input buffer with buffer got from port to get target data for ++ * encoder ++ */ ++ if (!pool->deactivated) { ++ if (!gst_buffer_map (frame->input_buffer, &in_info, GST_MAP_READ)) { ++ GST_ERROR_OBJECT (self, "Can not map input buffer"); ++ gst_omx_port_release_buffer (port, buf); ++ goto flow_error; ++ } ++ ++ if (buf->omx_buf->pBuffer != in_info.data) { ++ gst_omx_port_release_buffer (port, buf); ++ do { ++ acq_ret = gst_omx_port_acquire_buffer (port, &buf); ++ if (acq_ret != GST_OMX_ACQUIRE_BUFFER_OK) { ++ GST_ERROR_OBJECT (self, "Can acquire buffer from input port"); ++ return GST_FLOW_ERROR; ++ } ++ if (buf->omx_buf->pBuffer != in_info.data) ++ gst_omx_port_release_buffer (port, buf); ++ count += 1; ++ } while (buf->omx_buf->pBuffer != in_info.data ++ && count < port->port_def.nBufferCountActual * 3); ++ } ++ if (count == port->port_def.nBufferCountActual * 3) { ++ GST_ERROR_OBJECT (self, ++ "Can not get target OMXBuffer after 3 times searching"); ++ goto flow_error; ++ } ++ buf->omx_buf->nFilledLen = in_info.size; ++ gst_buffer_unmap (frame->input_buffer, &in_info); ++ } ++ } else { ++ /* Copy the buffer content in chunks of size as requested ++ * by the port */ ++ if (!gst_omx_video_enc_fill_buffer (self, frame->input_buffer, buf)) { ++ gst_omx_port_release_buffer (port, buf); ++ goto buffer_fill_error; ++ } + } + + timestamp = frame->pts; +@@ -1920,11 +2006,203 @@ static gboolean + gst_omx_video_enc_propose_allocation (GstVideoEncoder * encoder, + GstQuery * query) + { +- gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); ++ GstOMXVideoEnc *self; ++ GstOMXVideoEncClass *klass; ++ ++ self = GST_OMX_VIDEO_ENC (encoder); ++ klass = GST_OMX_VIDEO_ENC_GET_CLASS (encoder); ++ ++ GST_DEBUG_OBJECT (self, "gst_omx_video_enc_propose_allocation"); ++ if (self->no_copy == TRUE) { ++ /* Allocate buffers and propose them to upstream */ ++ GstCaps *caps; ++ GstVideoInfo info; ++ guint size; ++ OMX_PARAM_PORTDEFINITIONTYPE port_def; ++ guint max, min; ++ ++ gst_omx_port_get_port_definition (self->enc_in_port, &port_def); ++ ++ gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); ++ ++ gst_query_parse_allocation (query, &caps, NULL); ++ ++ if (caps == NULL) ++ return FALSE; ++ ++ if (!gst_video_info_from_caps (&info, caps)) ++ return FALSE; ++ ++ size = GST_VIDEO_INFO_SIZE (&info); ++ ++ if (gst_omx_component_get_state (self->enc, ++ GST_CLOCK_TIME_NONE) != OMX_StateLoaded) ++ return FALSE; ++ switch (info.finfo->format) { ++ case GST_VIDEO_FORMAT_I420: ++ port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar; ++ break; ++ case GST_VIDEO_FORMAT_NV12: ++ case GST_VIDEO_FORMAT_NV16: ++ port_def.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; ++ break; ++ default: ++ GST_ERROR_OBJECT (self, "Unsupported format %s", ++ gst_video_format_to_string (info.finfo->format)); ++ return FALSE; ++ break; ++ } ++ port_def.format.video.nFrameWidth = info.width; ++ if (klass->cdata.hacks & GST_OMX_HACK_RENESAS_ENCMC_STRIDE_ALIGN) { ++ switch (port_def.format.video.eColorFormat) { ++ case OMX_COLOR_FormatYUV420Planar: ++ port_def.format.video.nStride = GST_ROUND_UP_64 (info.width); ++ break; ++ case OMX_COLOR_FormatYUV420SemiPlanar: ++ port_def.format.video.nStride = GST_ROUND_UP_32 (info.width); ++ break; ++ default: ++ break; ++ } ++ } else ++ port_def.format.video.nStride = GST_ROUND_UP_4 (info.width); /* safe (?) default */ ++ port_def.format.video.nFrameHeight = info.height; ++ port_def.format.video.nSliceHeight = info.height; ++ switch (port_def.format.video.eColorFormat) { ++ case OMX_COLOR_FormatYUV420Planar: ++ case OMX_COLOR_FormatYUV420PackedPlanar: ++ port_def.nBufferSize = ++ (port_def.format.video.nStride * ++ port_def.format.video.nFrameHeight) + ++ 2 * ((port_def.format.video.nStride / 2) * ++ ((port_def.format.video.nFrameHeight + 1) / 2)); ++ break; ++ ++ case OMX_COLOR_FormatYUV420SemiPlanar: ++ port_def.nBufferSize = ++ (port_def.format.video.nStride * ++ port_def.format.video.nFrameHeight) + ++ (port_def.format.video.nStride * ++ ((port_def.format.video.nFrameHeight + 1) / 2)); ++ break; + +- return +- GST_VIDEO_ENCODER_CLASS +- (gst_omx_video_enc_parent_class)->propose_allocation (encoder, query); ++ default: ++ g_assert_not_reached (); ++ } ++ if (info.fps_n == 0) { ++ port_def.format.video.xFramerate = 0; ++ } else { ++ port_def.format.video.xFramerate = (info.fps_n) / (info.fps_d); ++ } ++ ++ if (gst_omx_port_update_port_definition (self->enc_in_port, ++ &port_def) != OMX_ErrorNone) ++ return FALSE; ++ ++ if (klass->set_format) { ++ if (!klass->set_format (self, self->enc_in_port, self->input_state)) { ++ GST_ERROR_OBJECT (self, "Subclass failed to set the new format"); ++ return FALSE; ++ } ++ } ++ GST_DEBUG_OBJECT (self, "Updating outport port definition"); ++ if (gst_omx_port_update_port_definition (self->enc_out_port, ++ NULL) != OMX_ErrorNone) ++ return FALSE; ++ ++ if (self->target_bitrate != 0xffffffff) { ++ OMX_VIDEO_PARAM_BITRATETYPE config; ++ OMX_ERRORTYPE err; ++ ++ GST_OMX_INIT_STRUCT (&config); ++ config.nPortIndex = self->enc_out_port->index; ++ /* Get default value of eControlRate to avoid setting an invalid value to it */ ++ err = gst_omx_component_get_parameter (self->enc, ++ OMX_IndexParamVideoBitrate, &config); ++ if (err != OMX_ErrorNone) ++ GST_ERROR_OBJECT (self, ++ "Fail to get parameter of video bitrate: %s (0x%08x)", ++ gst_omx_error_to_string (err), err); ++ ++ config.nTargetBitrate = self->target_bitrate; ++ if (self->control_rate != 0xffffffff) ++ config.eControlRate = self->control_rate; ++ ++ err = gst_omx_component_set_parameter (self->enc, ++ OMX_IndexParamVideoBitrate, &config); ++ if (err != OMX_ErrorNone) ++ GST_ERROR_OBJECT (self, "Failed to set bitrate parameter: %s (0x%08x)", ++ gst_omx_error_to_string (err), err); ++ } ++ ++ if (gst_omx_component_set_state (self->enc, OMX_StateIdle) != OMX_ErrorNone) ++ return FALSE; ++ ++ if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone) ++ return FALSE; ++ ++ if (gst_omx_port_allocate_buffers (self->enc_out_port) != OMX_ErrorNone) ++ return FALSE; ++ ++ GST_DEBUG_OBJECT (self, " gst_query_get_n_allocation_pools = %d", ++ gst_query_get_n_allocation_pools (query)); ++ if (gst_query_get_n_allocation_pools (query) == 0) { ++ GstStructure *structure; ++ GstAllocator *allocator = NULL; ++ GstAllocationParams params = { 0, }; ++ ++ if (gst_query_get_n_allocation_params (query) > 0) ++ gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms); ++ else ++ gst_query_add_allocation_param (query, allocator, ¶ms); ++ ++ self->in_port_pool = gst_omx_buffer_pool_new (GST_ELEMENT_CAST (self), ++ self->enc, self->enc_in_port); ++ ++ structure = gst_buffer_pool_get_config (self->in_port_pool); ++ gst_buffer_pool_config_set_params (structure, caps, ++ self->enc_in_port->port_def.nBufferSize, ++ self->enc_in_port->port_def.nBufferCountActual, ++ self->enc_in_port->port_def.nBufferCountActual); ++ ++ GST_DEBUG_OBJECT (self, " add allocator"); ++ gst_buffer_pool_config_get_params (structure, &caps, NULL, &min, &max); ++ gst_buffer_pool_config_set_allocator (structure, allocator, ¶ms); ++ ++ if (allocator) ++ gst_object_unref (allocator); ++ ++ if (!gst_buffer_pool_set_config (self->in_port_pool, structure)) { ++ GST_ERROR_OBJECT (self, "failed to set config"); ++ gst_object_unref (self->in_port_pool); ++ return FALSE; ++ } ++ ++ GST_OMX_BUFFER_POOL (self->in_port_pool)->allocating = TRUE; ++ ++ /* Wait for all buffers allocate */ ++ GST_DEBUG_OBJECT (self, "Activating pool"); ++ while (!gst_buffer_pool_set_active (self->in_port_pool, TRUE)) { ++ } ++ ++ GST_OMX_BUFFER_POOL (self->in_port_pool)->allocating = FALSE; ++ ++ gst_query_add_allocation_pool (query, self->in_port_pool, size, ++ port_def.nBufferCountActual, port_def.nBufferCountActual); ++ ++ gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); ++ ++ } ++ ++ return TRUE; ++ ++ } else { ++ gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); ++ ++ return ++ GST_VIDEO_ENCODER_CLASS ++ (gst_omx_video_enc_parent_class)->propose_allocation (encoder, query); ++ } + } + + static GstCaps * +diff --git a/omx/gstomxvideoenc.h b/omx/gstomxvideoenc.h +index e266537..7f80dca 100644 +--- a/omx/gstomxvideoenc.h ++++ b/omx/gstomxvideoenc.h +@@ -44,6 +44,7 @@ G_BEGIN_DECLS + + typedef struct _GstOMXVideoEnc GstOMXVideoEnc; + typedef struct _GstOMXVideoEncClass GstOMXVideoEncClass; ++typedef struct _GstOMXVideoEncPrivate GstOMXVideoEncPrivate; + + struct _GstOMXVideoEnc + { +@@ -53,6 +54,8 @@ struct _GstOMXVideoEnc + GstOMXComponent *enc; + GstOMXPort *enc_in_port, *enc_out_port; + ++ GstBufferPool *in_port_pool, *out_port_pool; ++ + /* < private > */ + GstVideoCodecState *input_state; + /* TRUE if the component is configured and saw +@@ -78,6 +81,14 @@ struct _GstOMXVideoEnc + guint32 quant_b_frames; + + GstFlowReturn downstream_flow_ret; ++ ++ /* Set TRUE to use GstBuffer of Bufferpool to transfer data to ++ * downstream ++ */ ++ gboolean no_copy; ++ ++ /* need? */ ++ GstOMXVideoEncPrivate *priv; + }; + + struct _GstOMXVideoEncClass +-- +1.7.10.4 + diff --git a/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0004-Export-a-first-dmabuf-file-descriptor-with-the-whole.patch b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0004-Export-a-first-dmabuf-file-descriptor-with-the-whole.patch new file mode 100644 index 0000000..6aa5d48 --- /dev/null +++ b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0004-Export-a-first-dmabuf-file-descriptor-with-the-whole.patch @@ -0,0 +1,65 @@ +From 1fe52cec8fec530a79eb3ab9f313bb860ec109be Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Thu, 1 Sep 2016 18:44:49 +0300 +Subject: [PATCH 04/10] Export a first dmabuf file descriptor with the whole + size + +This patch exports a dmabuf file descriptor from the head of Y plane +to the end of the buffer so that mapping the whole plane as +contiguous memory is available. + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + omx/gstomxbufferpool.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +diff --git a/omx/gstomxbufferpool.c b/omx/gstomxbufferpool.c +index 2585a72..b9fa769 100644 +--- a/omx/gstomxbufferpool.c ++++ b/omx/gstomxbufferpool.c +@@ -399,6 +399,7 @@ gst_omx_buffer_pool_create_buffer_contain_dmabuf (GstOMXBufferPool * self, + gint i; + gint page_size; + guint phys_addr = 0; ++ guint phys_size = 0; + + new_buf = gst_buffer_new (); + page_size = getpagesize (); +@@ -410,13 +411,15 @@ gst_omx_buffer_pool_create_buffer_contain_dmabuf (GstOMXBufferPool * self, + OMXR_MC_VIDEO_DECODERESULTTYPE *decode_res = + (OMXR_MC_VIDEO_DECODERESULTTYPE *) omx_buf->omx_buf->pOutputPortPrivate; + phys_addr = decode_res->pvPhysImageAddressY; ++ phys_size = (guint) omx_buf->omx_buf->nAllocLen; + } else if (GST_IS_OMX_VIDEO_ENC (self->element)) { + /* private data is a physical address of HW buffer */ + phys_addr = (guint) omx_buf->omx_buf->pInputPortPrivate; ++ phys_size = (guint) omx_buf->omx_buf->nAllocLen; + } + +- if (phys_addr == 0) { +- GST_ERROR_OBJECT (self, "Invalid phys addr for OMX buffer"); ++ if ((phys_addr == 0) || (phys_size == 0)) { ++ GST_ERROR_OBJECT (self, "Invalid phys range for OMX buffer"); + return NULL; + } + +@@ -428,8 +431,14 @@ gst_omx_buffer_pool_create_buffer_contain_dmabuf (GstOMXBufferPool * self, + /* Calculate offset between physical address and page boundary */ + page_offset[i] = plane_addr & (page_size - 1); + +- plane_size[i] = stride[i] * +- GST_VIDEO_INFO_COMP_HEIGHT (&self->video_info, i); ++ /* Export a dmabuf file descriptor from the head of Y plane to ++ * the end of the buffer so that mapping the whole plane as ++ * contiguous memory is available. */ ++ if (i == 0) ++ plane_size[i] = phys_size; ++ else ++ plane_size[i] = stride[i] * ++ GST_VIDEO_INFO_COMP_HEIGHT (&self->video_info, i); + + /* When downstream plugins do mapping from dmabuf fd it requires + * mapping from boundary page and size align for page size so +-- +1.7.10.4 + diff --git a/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0005-gssomxbufferpool-add-exported-flag.patch b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0005-gssomxbufferpool-add-exported-flag.patch new file mode 100644 index 0000000..c6b5c36 --- /dev/null +++ b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0005-gssomxbufferpool-add-exported-flag.patch @@ -0,0 +1,75 @@ +From c4e86a58041cd4408d283444dcba6f532a80697c Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Thu, 1 Sep 2016 17:33:44 +0300 +Subject: [PATCH 05/10] gssomxbufferpool: add exported flag + +This flag indicates that buffer are used outside of OMX component + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + omx/gstomx.c | 1 + + omx/gstomx.h | 5 +++++ + omx/gstomxbufferpool.c | 5 ++++- + 3 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/omx/gstomx.c b/omx/gstomx.c +index c018e72..5a916dc 100644 +--- a/omx/gstomx.c ++++ b/omx/gstomx.c +@@ -1663,6 +1663,7 @@ gst_omx_port_allocate_buffers_unlocked (GstOMXPort * port, + buf = g_slice_new0 (GstOMXBuffer); + buf->port = port; + buf->used = FALSE; ++ buf->exported = FALSE; + buf->settings_cookie = port->settings_cookie; + g_ptr_array_add (port->buffers, buf); + +diff --git a/omx/gstomx.h b/omx/gstomx.h +index 84980f3..27cb2a9 100644 +--- a/omx/gstomx.h ++++ b/omx/gstomx.h +@@ -279,6 +279,11 @@ struct _GstOMXBuffer { + */ + gboolean used; + ++ /* TRUE if the buffer exported outside the component, ++ * i.e. someone acquired this buffer ++ */ ++ gboolean exported; ++ + /* Cookie of the settings when this buffer was allocated */ + gint settings_cookie; + +diff --git a/omx/gstomxbufferpool.c b/omx/gstomxbufferpool.c +index b9fa769..1e0a14c 100644 +--- a/omx/gstomxbufferpool.c ++++ b/omx/gstomxbufferpool.c +@@ -695,7 +695,7 @@ gst_omx_buffer_pool_acquire_buffer (GstBufferPool * bpool, + pool->enc_buffer_index = 0; + + count += 1; +- } while (omx_buf->used == TRUE && ++ } while (omx_buf->exported == TRUE && + count < pool->port->port_def.nBufferCountActual * 3); + + if (count == pool->port->port_def.nBufferCountActual * 3) { +@@ -703,6 +703,7 @@ gst_omx_buffer_pool_acquire_buffer (GstBufferPool * bpool, + GST_ERROR_OBJECT (pool, + "Can not acquire buffer after 3 times searching"); + } else { ++ omx_buf->exported = TRUE; + *buffer = buf; + ret = GST_FLOW_OK; + } +@@ -731,6 +732,8 @@ gst_omx_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer) + omx_buf = + gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buffer), + gst_omx_buffer_data_quark); ++ if (GST_IS_OMX_VIDEO_ENC (pool->element)) ++ omx_buf->exported = FALSE; + if (pool->port->port_def.eDir == OMX_DirOutput && !omx_buf->used) { + /* Release back to the port, can be filled again */ + err = gst_omx_port_release_buffer (pool->port, omx_buf); +-- +1.7.10.4 + diff --git a/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0006-gstomxbufferpool-create-dmabuf-for-input-port.patch b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0006-gstomxbufferpool-create-dmabuf-for-input-port.patch new file mode 100644 index 0000000..93966b2 --- /dev/null +++ b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0006-gstomxbufferpool-create-dmabuf-for-input-port.patch @@ -0,0 +1,46 @@ +From 078a91a917a7b81cfcf523ac23b1c3e154506ef9 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Thu, 1 Sep 2016 17:43:35 +0300 +Subject: [PATCH 06/10] gstomxbufferpool: create dmabuf for input port + + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + omx/gstomxbufferpool.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/omx/gstomxbufferpool.c b/omx/gstomxbufferpool.c +index 1e0a14c..d86f9d8 100644 +--- a/omx/gstomxbufferpool.c ++++ b/omx/gstomxbufferpool.c +@@ -518,6 +518,7 @@ gst_omx_buffer_pool_alloc_buffer (GstBufferPool * bpool, + + pool->need_copy = FALSE; + } else { ++ gboolean dmabuf = FALSE; + GstMemory *mem; + const guint nstride = pool->port->port_def.format.video.nStride; + const guint nslice = pool->port->port_def.format.video.nSliceHeight; +@@ -552,8 +553,17 @@ gst_omx_buffer_pool_alloc_buffer (GstBufferPool * bpool, + + if (GST_IS_OMX_VIDEO_DEC (pool->element) && + GST_OMX_VIDEO_DEC (pool->element)->use_dmabuf == TRUE && +- (omx_buf->omx_buf->pOutputPortPrivate)) { +-#if defined (HAVE_MMNGRBUF) && defined (HAVE_VIDEODEC_EXT) ++ (omx_buf->omx_buf->pOutputPortPrivate)) ++ dmabuf = TRUE; ++ ++ ++ if (GST_IS_OMX_VIDEO_ENC (pool->element) && ++ GST_OMX_VIDEO_ENC (pool->element)->no_copy == TRUE && ++ (omx_buf->omx_buf->pInputPortPrivate)) ++ dmabuf = TRUE; ++ ++ if (dmabuf) { ++#if defined (HAVE_MMNGRBUF) + if (pool->allocator) + gst_object_unref (pool->allocator); + pool->allocator = gst_dmabuf_allocator_new (); +-- +1.7.10.4 + diff --git a/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0007-gstomxbufferpool-add-helper-to-get-omxbuffer-from-gs.patch b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0007-gstomxbufferpool-add-helper-to-get-omxbuffer-from-gs.patch new file mode 100644 index 0000000..ed9da8d --- /dev/null +++ b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0007-gstomxbufferpool-add-helper-to-get-omxbuffer-from-gs.patch @@ -0,0 +1,140 @@ +From 4abd8ac4f18f5baef5a23c7defdb12469192f9c5 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Thu, 1 Sep 2016 17:51:30 +0300 +Subject: [PATCH 07/10] gstomxbufferpool: add helper to get omxbuffer from + gstomxbuffer + + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + omx/gstomxbufferpool.c | 21 +++++++++++++++------ + omx/gstomxbufferpool.h | 2 ++ + omx/gstomxvideoenc.c | 26 ++++++++++++++++---------- + 3 files changed, 33 insertions(+), 16 deletions(-) + +diff --git a/omx/gstomxbufferpool.c b/omx/gstomxbufferpool.c +index d86f9d8..eb2fe9d 100644 +--- a/omx/gstomxbufferpool.c ++++ b/omx/gstomxbufferpool.c +@@ -361,6 +361,17 @@ wrong_video_caps: + } + } + ++GstOMXBuffer *gst_omx_buffer_get_omxbuffer (GstBuffer * buffer) ++{ ++ GstOMXBuffer *omx_buf; ++ ++ omx_buf = ++ gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buffer), ++ gst_omx_buffer_data_quark); ++ ++ return omx_buf; ++} ++ + #if defined (HAVE_MMNGRBUF) && defined (HAVE_VIDEODEC_EXT) + static gboolean + gst_omx_buffer_pool_export_dmabuf (GstOMXBufferPool * pool, +@@ -697,9 +708,7 @@ gst_omx_buffer_pool_acquire_buffer (GstBufferPool * bpool, + buf = g_ptr_array_index (pool->buffers, pool->enc_buffer_index); + g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); + +- omx_buf = +- gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buf), +- gst_omx_buffer_data_quark); ++ omx_buf = gst_omx_buffer_get_omxbuffer(buf); + pool->enc_buffer_index++; + if (pool->enc_buffer_index == pool->port->port_def.nBufferCountActual) + pool->enc_buffer_index = 0; +@@ -739,11 +748,11 @@ gst_omx_buffer_pool_release_buffer (GstBufferPool * bpool, GstBuffer * buffer) + g_assert (pool->component && pool->port); + + if (!pool->allocating && !pool->deactivated) { +- omx_buf = +- gst_mini_object_get_qdata (GST_MINI_OBJECT_CAST (buffer), +- gst_omx_buffer_data_quark); ++ omx_buf = gst_omx_buffer_get_omxbuffer(buffer); ++ + if (GST_IS_OMX_VIDEO_ENC (pool->element)) + omx_buf->exported = FALSE; ++ + if (pool->port->port_def.eDir == OMX_DirOutput && !omx_buf->used) { + /* Release back to the port, can be filled again */ + err = gst_omx_port_release_buffer (pool->port, omx_buf); +diff --git a/omx/gstomxbufferpool.h b/omx/gstomxbufferpool.h +index 09cab8d..0c6f18b 100644 +--- a/omx/gstomxbufferpool.h ++++ b/omx/gstomxbufferpool.h +@@ -101,6 +101,8 @@ GType gst_omx_buffer_pool_get_type (void); + + GstBufferPool *gst_omx_buffer_pool_new (GstElement * element, GstOMXComponent * component, GstOMXPort * port); + ++GstOMXBuffer *gst_omx_buffer_get_omxbuffer (GstBuffer * buffer); ++ + G_END_DECLS + + #endif /* __GST_OMX_BUFFER_POOL_H__ */ +diff --git a/omx/gstomxvideoenc.c b/omx/gstomxvideoenc.c +index b36c46e..e96ff28 100644 +--- a/omx/gstomxvideoenc.c ++++ b/omx/gstomxvideoenc.c +@@ -1786,7 +1786,8 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder, + gst_omx_error_to_string (err), err); + } + +- if (self->in_port_pool) { ++ if ((self->in_port_pool) && ++ (frame->input_buffer->pool == self->in_port_pool)) { + GstMapInfo in_info; + gint count = 0; + GstOMXBufferPool *pool = GST_OMX_BUFFER_POOL (self->in_port_pool); +@@ -1795,13 +1796,15 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder, + * encoder + */ + if (!pool->deactivated) { +- if (!gst_buffer_map (frame->input_buffer, &in_info, GST_MAP_READ)) { +- GST_ERROR_OBJECT (self, "Can not map input buffer"); +- gst_omx_port_release_buffer (port, buf); +- goto flow_error; ++ GstOMXBuffer *omx_buf; ++ ++ omx_buf = gst_omx_buffer_get_omxbuffer(frame->input_buffer); ++ if (!omx_buf) { ++ GST_ERROR_OBJECT (self, "Can not get OMXBuffer from GstBuffer"); ++ return GST_FLOW_ERROR; + } + +- if (buf->omx_buf->pBuffer != in_info.data) { ++ if (buf != omx_buf) { + gst_omx_port_release_buffer (port, buf); + do { + acq_ret = gst_omx_port_acquire_buffer (port, &buf); +@@ -1809,10 +1812,10 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder, + GST_ERROR_OBJECT (self, "Can acquire buffer from input port"); + return GST_FLOW_ERROR; + } +- if (buf->omx_buf->pBuffer != in_info.data) ++ if (buf != omx_buf) + gst_omx_port_release_buffer (port, buf); + count += 1; +- } while (buf->omx_buf->pBuffer != in_info.data ++ } while (buf != omx_buf + && count < port->port_def.nBufferCountActual * 3); + } + if (count == port->port_def.nBufferCountActual * 3) { +@@ -1820,8 +1823,11 @@ gst_omx_video_enc_handle_frame (GstVideoEncoder * encoder, + "Can not get target OMXBuffer after 3 times searching"); + goto flow_error; + } +- buf->omx_buf->nFilledLen = in_info.size; +- gst_buffer_unmap (frame->input_buffer, &in_info); ++ GST_DEBUG_OBJECT (self, "found target OMXBuffer %p", buf); ++ //buf->omx_buf->nFilledLen = gst_buffer_get_size (frame->input_buffer); ++ buf->omx_buf->nFilledLen = buf->omx_buf->nAllocLen - buf->omx_buf->nOffset; ++ GST_DEBUG_OBJECT (self, "set nFilledLen = %d", buf->omx_buf->nFilledLen); ++ + } + } else { + /* Copy the buffer content in chunks of size as requested +-- +1.7.10.4 + diff --git a/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0008-gstomxenc-do-not-allocate-output-buffers-two-times.patch b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0008-gstomxenc-do-not-allocate-output-buffers-two-times.patch new file mode 100644 index 0000000..8f97e7f --- /dev/null +++ b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0008-gstomxenc-do-not-allocate-output-buffers-two-times.patch @@ -0,0 +1,47 @@ +From d1025433f05ebeb1a790abefa5cfc48455bf441c Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Thu, 1 Sep 2016 17:57:10 +0300 +Subject: [PATCH 08/10] gstomxenc: do not allocate output buffers two times + + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + omx/gstomxvideoenc.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +diff --git a/omx/gstomxvideoenc.c b/omx/gstomxvideoenc.c +index e96ff28..19a0eb9 100644 +--- a/omx/gstomxvideoenc.c ++++ b/omx/gstomxvideoenc.c +@@ -1338,18 +1338,21 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder, + if (gst_omx_port_mark_reconfigured (self->enc_in_port) != OMX_ErrorNone) + return FALSE; + } else { +- if (gst_omx_component_set_state (self->enc, OMX_StateIdle) != OMX_ErrorNone) +- return FALSE; +- +- /* Need to allocate buffers to reach Idle state */ ++ /* if is not done in propose_allocation */ + if (!self->in_port_pool) { ++ if (gst_omx_component_set_state (self->enc, OMX_StateIdle) != OMX_ErrorNone) ++ return FALSE; ++ ++ /* Need to allocate buffers to reach Idle state */ ++ /* Allocate for input port */ + if (gst_omx_port_allocate_buffers (self->enc_in_port) != OMX_ErrorNone) + return FALSE; ++ ++ /* Allocate for output port */ ++ if (gst_omx_port_allocate_buffers (self->enc_out_port) != OMX_ErrorNone) ++ return FALSE; + } + +- /* Allocate for output port */ +- if (gst_omx_port_allocate_buffers (self->enc_out_port) != OMX_ErrorNone) +- return FALSE; + if (gst_omx_component_get_state (self->enc, + GST_CLOCK_TIME_NONE) != OMX_StateIdle) + return FALSE; +-- +1.7.10.4 + diff --git a/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0009-gstomxenc-move-encoder-disable-code-to-separate-func.patch b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0009-gstomxenc-move-encoder-disable-code-to-separate-func.patch new file mode 100644 index 0000000..8404acd --- /dev/null +++ b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0009-gstomxenc-move-encoder-disable-code-to-separate-func.patch @@ -0,0 +1,113 @@ +From 0a9f0aa8271b0fc18c7e9781e3d0bc215ba2fd02 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Thu, 1 Sep 2016 17:58:33 +0300 +Subject: [PATCH 09/10] gstomxenc: move encoder disable code to separate + function + + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + omx/gstomxvideoenc.c | 79 ++++++++++++++++++++++++++++---------------------- + 1 file changed, 45 insertions(+), 34 deletions(-) + +diff --git a/omx/gstomxvideoenc.c b/omx/gstomxvideoenc.c +index 19a0eb9..6720648 100644 +--- a/omx/gstomxvideoenc.c ++++ b/omx/gstomxvideoenc.c +@@ -1147,6 +1147,49 @@ gst_omx_video_enc_get_supported_colorformats (GstOMXVideoEnc * self) + } + + static gboolean ++gst_omx_video_enc_disable(GstVideoEncoder * encoder) ++{ ++ GstOMXVideoEnc *self; ++ ++ self = GST_OMX_VIDEO_ENC (encoder); ++ ++ GST_DEBUG_OBJECT (self, "Need to disable and drain encoder"); ++ gst_omx_video_enc_drain (self, FALSE); ++ gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE); ++ ++ /* Wait until the srcpad loop is finished, ++ * unlock GST_VIDEO_ENCODER_STREAM_LOCK to prevent deadlocks ++ * caused by using this lock from inside the loop function */ ++ GST_VIDEO_ENCODER_STREAM_UNLOCK (self); ++ gst_pad_stop_task (GST_VIDEO_ENCODER_SRC_PAD (encoder)); ++ GST_VIDEO_ENCODER_STREAM_LOCK (self); ++ ++ if (gst_omx_port_set_enabled (self->enc_in_port, FALSE) != OMX_ErrorNone) ++ return FALSE; ++ if (gst_omx_port_set_enabled (self->enc_out_port, FALSE) != OMX_ErrorNone) ++ return FALSE; ++ if (gst_omx_port_wait_buffers_released (self->enc_in_port, ++ 5 * GST_SECOND) != OMX_ErrorNone) ++ return FALSE; ++ if (gst_omx_port_wait_buffers_released (self->enc_out_port, ++ 1 * GST_SECOND) != OMX_ErrorNone) ++ return FALSE; ++ if (gst_omx_port_deallocate_buffers (self->enc_in_port) != OMX_ErrorNone) ++ return FALSE; ++ if (gst_omx_port_deallocate_buffers (self->enc_out_port) != OMX_ErrorNone) ++ return FALSE; ++ if (gst_omx_port_wait_enabled (self->enc_in_port, ++ 1 * GST_SECOND) != OMX_ErrorNone) ++ return FALSE; ++ if (gst_omx_port_wait_enabled (self->enc_out_port, ++ 1 * GST_SECOND) != OMX_ErrorNone) ++ return FALSE; ++ ++ GST_DEBUG_OBJECT (self, "Encoder drained and disabled"); ++ return TRUE; ++} ++ ++static gboolean + gst_omx_video_enc_set_format (GstVideoEncoder * encoder, + GstVideoCodecState * state) + { +@@ -1176,41 +1219,9 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder, + * we have to disable the port and re-allocate all buffers. If no real + * format change happened we can just exit here. + */ +- if (needs_disable) { +- GST_DEBUG_OBJECT (self, "Need to disable and drain encoder"); +- gst_omx_video_enc_drain (self, FALSE); +- gst_omx_port_set_flushing (self->enc_out_port, 5 * GST_SECOND, TRUE); +- +- /* Wait until the srcpad loop is finished, +- * unlock GST_VIDEO_ENCODER_STREAM_LOCK to prevent deadlocks +- * caused by using this lock from inside the loop function */ +- GST_VIDEO_ENCODER_STREAM_UNLOCK (self); +- gst_pad_stop_task (GST_VIDEO_ENCODER_SRC_PAD (encoder)); +- GST_VIDEO_ENCODER_STREAM_LOCK (self); +- +- if (gst_omx_port_set_enabled (self->enc_in_port, FALSE) != OMX_ErrorNone) ++ if (needs_disable) ++ if (!gst_omx_video_enc_disable(encoder)) + return FALSE; +- if (gst_omx_port_set_enabled (self->enc_out_port, FALSE) != OMX_ErrorNone) +- return FALSE; +- if (gst_omx_port_wait_buffers_released (self->enc_in_port, +- 5 * GST_SECOND) != OMX_ErrorNone) +- return FALSE; +- if (gst_omx_port_wait_buffers_released (self->enc_out_port, +- 1 * GST_SECOND) != OMX_ErrorNone) +- return FALSE; +- if (gst_omx_port_deallocate_buffers (self->enc_in_port) != OMX_ErrorNone) +- return FALSE; +- if (gst_omx_port_deallocate_buffers (self->enc_out_port) != OMX_ErrorNone) +- return FALSE; +- if (gst_omx_port_wait_enabled (self->enc_in_port, +- 1 * GST_SECOND) != OMX_ErrorNone) +- return FALSE; +- if (gst_omx_port_wait_enabled (self->enc_out_port, +- 1 * GST_SECOND) != OMX_ErrorNone) +- return FALSE; +- +- GST_DEBUG_OBJECT (self, "Encoder drained and disabled"); +- } + + negotiation_map = gst_omx_video_enc_get_supported_colorformats (self); + if (!negotiation_map) { +-- +1.7.10.4 + diff --git a/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0010-omxvideodec-support-creating-buffers-using-sink.patch b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0010-omxvideodec-support-creating-buffers-using-sink.patch new file mode 100644 index 0000000..bd2b91c --- /dev/null +++ b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/0010-omxvideodec-support-creating-buffers-using-sink.patch @@ -0,0 +1,186 @@ +From 58d8ea72ec78cb17cf75c82c67a69e9bd383c3b3 Mon Sep 17 00:00:00 2001 +From: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +Date: Thu, 1 Sep 2016 20:09:03 +0300 +Subject: [PATCH 10/10] omxvideodec: support creating buffers using sink + +Used for zero-copy output to wayland/weston + +Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com> +--- + omx/gstomxbufferpool.c | 107 +++++++++++++++++++++++++++++++++++++++++++++--- + omx/gstomxvideodec.c | 11 ++++- + 2 files changed, 111 insertions(+), 7 deletions(-) + +diff --git a/omx/gstomxbufferpool.c b/omx/gstomxbufferpool.c +index eb2fe9d..60b25ef 100644 +--- a/omx/gstomxbufferpool.c ++++ b/omx/gstomxbufferpool.c +@@ -372,6 +372,73 @@ GstOMXBuffer *gst_omx_buffer_get_omxbuffer (GstBuffer * buffer) + return omx_buf; + } + ++#ifdef HAVE_MMNGRBUF ++static GstBuffer * ++gst_omx_buffer_pool_request_videosink_buffer_creation (GstOMXBufferPool * pool, ++ gint dmabuf_fd[GST_VIDEO_MAX_PLANES], gpointer plane_buf[GST_VIDEO_MAX_PLANES], gint stride[GST_VIDEO_MAX_PLANES]) ++{ ++ GstQuery *query; ++ GValue val = { 0, }; ++ GstStructure *structure; ++ const GValue *value; ++ GstBuffer *buffer; ++ GArray *dmabuf_array; ++ GArray *stride_array; ++ GArray *planebuf_array; ++ gint n_planes; ++ gint i; ++ ++ g_value_init (&val, G_TYPE_POINTER); ++ g_value_set_pointer (&val, (gpointer) pool->allocator); ++ ++ dmabuf_array = g_array_new (FALSE, FALSE, sizeof (gint)); ++ stride_array = g_array_new (FALSE, FALSE, sizeof (gint)); ++ planebuf_array = g_array_new (FALSE, FALSE, sizeof (gpointer)); ++ ++ n_planes = GST_VIDEO_INFO_N_PLANES (&pool->video_info); ++ for (i = 0; i < n_planes; i++) { ++ g_array_append_val (dmabuf_array, dmabuf_fd[i]); ++ g_array_append_val (stride_array, stride[i]); ++ g_array_append_val (planebuf_array, plane_buf[i]); ++ } ++ ++ structure = gst_structure_new ("videosink_buffer_creation_request", ++ "width", G_TYPE_INT, pool->port->port_def.format.video.nFrameWidth, ++ "height", G_TYPE_INT, pool->port->port_def.format.video.nFrameHeight, ++ "stride", G_TYPE_ARRAY, stride_array, ++ "dmabuf", G_TYPE_ARRAY, dmabuf_array, ++ "planebuf", G_TYPE_ARRAY, planebuf_array, ++ "allocator", G_TYPE_POINTER, &val, ++ "format", G_TYPE_STRING, ++ gst_video_format_to_string (pool->video_info.finfo->format), ++ "n_planes", G_TYPE_INT, n_planes, NULL); ++ ++ query = gst_query_new_custom (GST_QUERY_CUSTOM, structure); ++ ++ GST_DEBUG_OBJECT (pool, "send a videosink_buffer_creation_request query"); ++ ++ if (!gst_pad_peer_query (GST_VIDEO_DECODER_SRC_PAD (pool->element), query)) { ++ GST_ERROR_OBJECT (pool, "videosink_buffer_creation_request query failed"); ++ return NULL; ++ } ++ ++ value = gst_structure_get_value (structure, "buffer"); ++ buffer = gst_value_get_buffer (value); ++ if (buffer == NULL) { ++ GST_ERROR_OBJECT (pool, ++ "could not get a buffer from videosink_buffer_creation query"); ++ return NULL; ++ } ++ ++ gst_query_unref (query); ++ ++ g_array_free (dmabuf_array, TRUE); ++ g_array_free (stride_array, TRUE); ++ ++ return buffer; ++} ++#endif ++ + #if defined (HAVE_MMNGRBUF) && defined (HAVE_VIDEODEC_EXT) + static gboolean + gst_omx_buffer_pool_export_dmabuf (GstOMXBufferPool * pool, +@@ -406,6 +473,7 @@ gst_omx_buffer_pool_create_buffer_contain_dmabuf (GstOMXBufferPool * self, + gint plane_size_ext[GST_VIDEO_MAX_PLANES]; + gint dmabuf_id[GST_VIDEO_MAX_PLANES]; + gint page_offset[GST_VIDEO_MAX_PLANES]; ++ gint plane_buf[GST_VIDEO_MAX_PLANES]; + GstBuffer *new_buf; + gint i; + gint page_size; +@@ -450,6 +518,7 @@ gst_omx_buffer_pool_create_buffer_contain_dmabuf (GstOMXBufferPool * self, + else + plane_size[i] = stride[i] * + GST_VIDEO_INFO_COMP_HEIGHT (&self->video_info, i); ++ plane_buf[i] = omx_buf->omx_buf->pBuffer + offset[i]; + + /* When downstream plugins do mapping from dmabuf fd it requires + * mapping from boundary page and size align for page size so +@@ -472,14 +541,40 @@ gst_omx_buffer_pool_create_buffer_contain_dmabuf (GstOMXBufferPool * self, + gst_buffer_append_memory (new_buf, mem); + } + +- g_ptr_array_add (self->buffers, new_buf); +- gst_buffer_add_video_meta_full (new_buf, GST_VIDEO_FRAME_FLAG_NONE, +- GST_VIDEO_INFO_FORMAT (&self->video_info), +- GST_VIDEO_INFO_WIDTH (&self->video_info), +- GST_VIDEO_INFO_HEIGHT (&self->video_info), +- GST_VIDEO_INFO_N_PLANES (&self->video_info), offset, stride); ++ if (self->vsink_buf_req_supported) { ++ new_buf = gst_omx_buffer_pool_request_videosink_buffer_creation (self, ++ dmabuf_fd, plane_buf, stride); ++ if (!new_buf) { ++ GST_ERROR_OBJECT (self, "creating dmabuf using videosink failed"); ++ goto err; ++ } ++ new_buf->pool = self; ++ } else { ++ new_buf = gst_buffer_new (); ++ for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&self->video_info); i++) { ++ GstMemory *mem; ++ /* Set offset's information */ ++ mem = gst_dmabuf_allocator_alloc (self->allocator, dmabuf_fd[i], ++ plane_size_ext[i]); ++ mem->offset = page_offset[i]; ++ mem->size = plane_size[i]; ++ gst_buffer_append_memory (new_buf, mem); ++ } ++ ++ gst_buffer_add_video_meta_full (new_buf, GST_VIDEO_FRAME_FLAG_NONE, ++ GST_VIDEO_INFO_FORMAT (&self->video_info), ++ GST_VIDEO_INFO_WIDTH (&self->video_info), ++ GST_VIDEO_INFO_HEIGHT (&self->video_info), ++ GST_VIDEO_INFO_N_PLANES (&self->video_info), offset, stride); ++ } + ++ GST_ERROR_OBJECT (self, "got buffer %p from pool %p", ++ new_buf, new_buf->pool); ++ g_ptr_array_add (self->buffers, new_buf); + return new_buf; ++ ++err: ++ return NULL; + } + #endif + +diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c +index 25b6b30..44b706a 100644 +--- a/omx/gstomxvideodec.c ++++ b/omx/gstomxvideodec.c +@@ -2350,6 +2350,8 @@ gst_omx_video_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query) + &GST_OMX_BUFFER_POOL (self->out_port_pool)->vsink_buf_req_supported); + gst_object_unref (pool); + update_pool = TRUE; ++ GST_ERROR_OBJECT (self, "vsink_buf_req_supported %d", ++ GST_OMX_BUFFER_POOL (self->out_port_pool)->vsink_buf_req_supported); + } + + /* Set pool parameters to our own configuration */ +@@ -2372,7 +2374,14 @@ gst_omx_video_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query) + } + + GST_OMX_BUFFER_POOL (self->out_port_pool)->allocating = TRUE; +- gst_buffer_pool_set_active (self->out_port_pool, TRUE); ++ /* This now allocates all the buffers */ ++ if (!gst_buffer_pool_set_active (self->out_port_pool, TRUE)) { ++ GST_INFO_OBJECT (self, "Failed to activate internal pool"); ++ gst_object_unref (self->out_port_pool); ++ self->out_port_pool = NULL; ++ } else { ++ GST_OMX_BUFFER_POOL (self->out_port_pool)->allocating = FALSE; ++ } + + /* This video buffer pool created below will not be used, just setting to + * the gstvideodecoder class through a query, because it is +-- +1.7.10.4 + diff --git a/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/gstomx.conf b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/gstomx.conf new file mode 100644 index 0000000..375e201 --- /dev/null +++ b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx/gstomx.conf @@ -0,0 +1,62 @@ +[omxh263dec] +type-name=GstOMXH263Dec +core-name=/usr/local/lib/libomxr_core.so +component-name=OMX.RENESAS.VIDEO.DECODER.H263 +rank=512 +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-component-role;default-pix-aspect-ratio + +[omxh264dec] +type-name=GstOMXH264Dec +core-name=/usr/local/lib/libomxr_core.so +component-name=OMX.RENESAS.VIDEO.DECODER.H264 +rank=512 +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-component-role;default-pix-aspect-ratio + +[omxmpeg2videodec] +type-name=GstOMXMPEG2VideoDec +core-name=/usr/local/lib/libomxr_core.so +component-name=OMX.RENESAS.VIDEO.DECODER.MPEG2 +rank=512 +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-component-role;default-pix-aspect-ratio + +[omxmpeg4videodec] +type-name=GstOMXMPEG4VideoDec +core-name=/usr/local/lib/libomxr_core.so +component-name=OMX.RENESAS.VIDEO.DECODER.MPEG4 +rank=512 +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-component-role;default-pix-aspect-ratio + +[omxvc1videodec] +type-name=GstOMXVC1VideoDec +core-name=/usr/local/lib/libomxr_core.so +component-name=OMX.RENESAS.VIDEO.DECODER.VC1 +rank=512 +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-component-role;default-pix-aspect-ratio + +[omxaacdec] +type-name=GstOMXAACDec +core-name=/usr/local/lib/libomxr_core.so +component-name=OMX.RENESAS.AUDIO.DECODER.AAC +rank=256 +in-port-index=0 +out-port-index=1 +hacks= + +[omxh264enc] +type-name=GstOMXH264Enc +core-name=/usr/local/lib/libomxr_core.so +component-name=OMX.RENESAS.VIDEO.ENCODER.H264 +rank=256 +in-port-index=0 +out-port-index=1 +hacks=renesas-encmc-stride-align diff --git a/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx_1.0.0.bbappend b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx_1.0.0.bbappend index 95706e5..426f0c4 100644 --- a/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx_1.0.0.bbappend +++ b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-omx_1.0.0.bbappend @@ -1,20 +1,24 @@ require ../../include/gles-control.inc SRC_URI_rcar-gen2 = "git://github.com/renesas-devel/gst-omx.git;protocol=git;branch=RCAR-GEN2/1.0.0" -SRCREV_rcar-gen2 = "05563465faad99243ee2dd30547e3075eb8cf5e3" +SRCREV_rcar-gen2 = "${@'e0a23fb50ec211a8058eac223847bbcc574fb343' \ + if '1' in '${USE_GLES_WAYLAND}' else '05563465faad99243ee2dd30547e3075eb8cf5e3'}" -LIC_FILES_CHKSUM_remove_rcar-gen2 = " file://omx/gstomx.h;beginline=1;endline=21;md5=5c8e1fca32704488e76d2ba9ddfa935f" +LIC_FILES_CHKSUM_remove_rcar-gen2 = " file://omx/gstomx.h;beginline=1;endline=21;md5=5c8e1fca32704488e76d2ba9ddfa935f" LIC_FILES_CHKSUM_append_rcar-gen2 = " file://omx/gstomx.h;beginline=1;endline=22;md5=17e5f2943dace9e5cde4a8587a31e8f9" S = "${WORKDIR}/git" -do_configure_prepend() { +do_configure() { cd ${S} ./autogen.sh --noconfigure cd ${B} + oe_runconf } DEPENDS_append_rcar-gen2 = " omx-user-module mmngrbuf-user-module" -EXTRA_OECONF_append_rcar-gen2 = " --with-omx-target=rcar --enable-experimental \ +EXTRA_OECONF_append_rcar-gen2 = " \ + --with-omx-target=rcar --enable-experimental \ + '${@'--enable-nv12-page-alignment' if '${USE_GLES_WAYLAND}' == '1' else ''}' \ '${@'--disable-dmabuf' if '${USE_GLES}' == '0' and '${USE_WAYLAND}' == '1' else ''}'" # Overwrite do_install[postfuncs] += " set_omx_core_name " @@ -22,6 +26,23 @@ EXTRA_OECONF_append_rcar-gen2 = " --with-omx-target=rcar --enable-experimental \ revert_omx_core_name() { sed -i -e "s;^core-name=.*;core-name=/usr/local/lib/libomxr_core.so;" "${D}/etc/xdg/gstomx.conf" } + REVERT_OMX_CORE_NAME = "" REVERT_OMX_CORE_NAME_rcar-gen2 = "revert_omx_core_name" do_install[postfuncs] += "${REVERT_OMX_CORE_NAME}" + +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +SRC_URI_append = " \ + file://0001-omx-videodec-add-planebuf-to-allocation-request.patch \ + file://0002-Fixed-memory-corruption-and-bad-access.patch \ + file://0003-omxvideoenc-export-dmafd-buffer-through-own-buffer-p.patch \ + file://0004-Export-a-first-dmabuf-file-descriptor-with-the-whole.patch \ + file://0005-gssomxbufferpool-add-exported-flag.patch \ + file://0006-gstomxbufferpool-create-dmabuf-for-input-port.patch \ + file://0007-gstomxbufferpool-add-helper-to-get-omxbuffer-from-gs.patch \ + file://0008-gstomxenc-do-not-allocate-output-buffers-two-times.patch \ + file://0009-gstomxenc-move-encoder-disable-code-to-separate-func.patch \ + file://0010-omxvideodec-support-creating-buffers-using-sink.patch \ + file://gstomx.conf \ +" diff --git a/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.2.3.bbappend b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.2.3.bbappend index 8262f16..d09f5aa 100644 --- a/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.2.3.bbappend +++ b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.2.3.bbappend @@ -21,7 +21,7 @@ do_configure_prepend() { # for wayland PACKAGECONFIG_remove_rcar-gen2 = "${@'orc' if '1' in '${USE_GLES_WAYLAND}' else ''}" -PACKAGECONFIG_append_rcar-gen2 = " faad ${@base_contains('USE_GLES_WAYLAND', '1', 'wayland', '', d)}" +PACKAGECONFIG_append_rcar-gen2 = " faad ${@bb.utils.contains('USE_GLES_WAYLAND', '1', 'wayland', '', d)}" DEPENDS += "wayland-kms" RDEPENDS_${PN} = "libwayland-egl" diff --git a/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.2.3.bbappend b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.2.3.bbappend index 18d4b64..7faa133 100644 --- a/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.2.3.bbappend +++ b/meta-rcar-gen2/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.2.3.bbappend @@ -25,7 +25,7 @@ VSPFILTER_CONFIGS = " \ " # For wayland -PACKAGECONFIG_remove_rcar-gen2 = "${@base_contains("DISTRO_FEATURES", "wayland", "orc", "", d)}" +PACKAGECONFIG_remove_rcar-gen2 = "${@bb.utils.contains("DISTRO_FEATURES", "wayland", "orc", "", d)}" SRC_URI_append_rcar-gen2 = \ "${@'${VSPFILTER_CONFIGS}' \ diff --git a/meta-rcar-gen2/recipes-multimedia/packagegroups/packagegroup-rcar-gen2-multimedia.bb b/meta-rcar-gen2/recipes-multimedia/packagegroups/packagegroup-rcar-gen2-multimedia.bb index 688c6b7..25afdb4 100644 --- a/meta-rcar-gen2/recipes-multimedia/packagegroups/packagegroup-rcar-gen2-multimedia.bb +++ b/meta-rcar-gen2/recipes-multimedia/packagegroups/packagegroup-rcar-gen2-multimedia.bb @@ -23,6 +23,10 @@ MULTIMEDIA_PACKAGES ="\ libmemcpy \ " +MULTIMEDIA_PACKAGES_append = " \ + ${@ "vsp2-kernel-module" if "${USE_GLES_WAYLAND}" == "1" else "" } \ +" + RDEPENDS_packagegroup-rcar-gen2-multimedia = "\ ${@ "${MULTIMEDIA_PACKAGES}" if "${USE_MULTIMEDIA}" == "1" else "" } \ media-ctl \ @@ -41,7 +45,7 @@ RDEPENDS_packagegroup-rcar-gen2-multimedia = "\ gstreamer1.0-plugins-bad-faad \ gstreamer1.0-plugins-bad-mpegtsdemux \ gstreamer1.0-plugins-bad-debugutilsbad \ - ${@base_contains("LICENSE_FLAGS_WHITELIST", "commercial", "gstreamer1.0-omx gstreamer1.0-plugins-ugly-asf", "", d )} \ + ${@bb.utils.contains("LICENSE_FLAGS_WHITELIST", "commercial", "gstreamer1.0-omx gstreamer1.0-plugins-ugly-asf", "", d )} \ ${@base_conditional("USE_GLES_WAYLAND", "1", "gstreamer1.0-plugins-base-vspfilter", "", d )} \ " diff --git a/meta-rcar-gen2/scripts/setup_mm_packages.sh b/meta-rcar-gen2/scripts/setup_mm_packages.sh index a2a87da..0d312d3 100644 --- a/meta-rcar-gen2/scripts/setup_mm_packages.sh +++ b/meta-rcar-gen2/scripts/setup_mm_packages.sh @@ -20,19 +20,17 @@ function copy_mm_packages() { if [ ! -d binary-tmp ]; then if [ -f $DOWNLOAD_DIR/$ZIP_1 -a -f $DOWNLOAD_DIR/$ZIP_2 ]; then mkdir binary-tmp - cd binary-tmp - unzip -o $DOWNLOAD_DIR/$ZIP_1 - unzip -o $DOWNLOAD_DIR/$ZIP_2 - cd .. + unzip -o $DOWNLOAD_DIR/$ZIP_1 -d binary-tmp + unzip -o $DOWNLOAD_DIR/$ZIP_2 -d binary-tmp else echo -e echo -e "ERROR: Missing Renesas proprietary software packages for Porter board." echo -e echo -e " The graphics and multimedia acceleration packages for " - echo -e " the R-Car M2 Porter board can be download from :" + echo -e " the R-Car M2 Porter board can be downloaded from :" echo -e " <http://www.renesas.com/secret/r_car_download/rcar_demoboard.jsp>" echo -e - echo -e " These 2 files from there should be store in" + echo -e " These 2 files from there should be stored in your" echo -e " '$DOWNLOAD_DIR' directory." echo -e " $ZIP_1" echo -e " $ZIP_2" |