From: Gurkirpal Singh Date: Sat, 12 Aug 2017 16:07:15 +0000 (+0530) Subject: st/omx_bellagio: Rename state tracker and option X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6a8aa11c207b99920b9306b209f071a0e3fe8b43;p=mesa.git st/omx_bellagio: Rename state tracker and option Changes --enable-omx option to --enable-omx-bellagio Signed-off-by: Gurkirpal Singh Reviewed-and-Tested-by: Julien Isorce Acked-by: Christian König --- diff --git a/configure.ac b/configure.ac index d0d4c0dfd1d..605c9b4e992 100644 --- a/configure.ac +++ b/configure.ac @@ -1228,9 +1228,14 @@ AC_ARG_ENABLE([vdpau], [enable_vdpau=auto]) AC_ARG_ENABLE([omx], [AS_HELP_STRING([--enable-omx], - [enable OpenMAX library @<:@default=disabled@:>@])], - [enable_omx="$enableval"], - [enable_omx=no]) + [DEPRECATED: Use --enable-omx-bellagio instead @<:@default=auto@:>@])], + [AC_MSG_ERROR([--enable-omx is deprecated. Use --enable-omx-bellagio instead.])], + []) +AC_ARG_ENABLE([omx-bellagio], + [AS_HELP_STRING([--enable-omx-bellagio], + [enable OpenMAX Bellagio library @<:@default=disabled@:>@])], + [enable_omx_bellagio="$enableval"], + [enable_omx_bellagio=no]) AC_ARG_ENABLE([va], [AS_HELP_STRING([--enable-va], [enable va library @<:@default=auto@:>@])], @@ -1281,7 +1286,7 @@ if test "x$enable_opengl" = xno -a \ "x$enable_xa" = xno -a \ "x$enable_xvmc" = xno -a \ "x$enable_vdpau" = xno -a \ - "x$enable_omx" = xno -a \ + "x$enable_omx_bellagio" = xno -a \ "x$enable_va" = xno -a \ "x$enable_opencl" = xno; then AC_MSG_ERROR([at least one API should be enabled]) @@ -2126,8 +2131,8 @@ if test -n "$with_gallium_drivers" -a "x$with_gallium_drivers" != xswrast; then PKG_CHECK_EXISTS([vdpau >= $VDPAU_REQUIRED], [enable_vdpau=yes], [enable_vdpau=no]) fi - if test "x$enable_omx" = xauto -a "x$have_omx_platform" = xyes; then - PKG_CHECK_EXISTS([libomxil-bellagio >= $LIBOMXIL_BELLAGIO_REQUIRED], [enable_omx=yes], [enable_omx=no]) + if test "x$enable_omx_bellagio" = xauto -a "x$have_omx_platform" = xyes; then + PKG_CHECK_EXISTS([libomxil-bellagio >= $LIBOMXIL_BELLAGIO_REQUIRED], [enable_omx_bellagio=yes], [enable_omx_bellagio=no]) fi if test "x$enable_va" = xauto -a "x$have_va_platform" = xyes; then @@ -2138,7 +2143,7 @@ fi if test "x$enable_dri" = xyes -o \ "x$enable_xvmc" = xyes -o \ "x$enable_vdpau" = xyes -o \ - "x$enable_omx" = xyes -o \ + "x$enable_omx_bellagio" = xyes -o \ "x$enable_va" = xyes; then need_gallium_vl=yes fi @@ -2146,7 +2151,7 @@ AM_CONDITIONAL(NEED_GALLIUM_VL, test "x$need_gallium_vl" = xyes) if test "x$enable_xvmc" = xyes -o \ "x$enable_vdpau" = xyes -o \ - "x$enable_omx" = xyes -o \ + "x$enable_omx_bellagio" = xyes -o \ "x$enable_va" = xyes; then PKG_CHECK_MODULES([VL], [x11-xcb xcb xcb-dri2 >= $XCBDRI2_REQUIRED]) need_gallium_vl_winsys=yes @@ -2172,14 +2177,14 @@ if test "x$enable_vdpau" = xyes; then fi AM_CONDITIONAL(HAVE_ST_VDPAU, test "x$enable_vdpau" = xyes) -if test "x$enable_omx" = xyes; then +if test "x$enable_omx_bellagio" = xyes; then if test "x$have_omx_platform" != xyes; then AC_MSG_ERROR([OMX requires at least one of the x11 or drm platforms]) fi - PKG_CHECK_MODULES([OMX], [libomxil-bellagio >= $LIBOMXIL_BELLAGIO_REQUIRED]) - gallium_st="$gallium_st omx" + PKG_CHECK_MODULES([OMX_BELLAGIO], [libomxil-bellagio >= $LIBOMXIL_BELLAGIO_REQUIRED]) + gallium_st="$gallium_st omx_bellagio" fi -AM_CONDITIONAL(HAVE_ST_OMX, test "x$enable_omx" = xyes) +AM_CONDITIONAL(HAVE_ST_OMX_BELLAGIO, test "x$enable_omx_bellagio" = xyes) if test "x$enable_va" = xyes; then if test "x$have_va_platform" != xyes; then @@ -2341,15 +2346,15 @@ AC_ARG_WITH([vdpau-libdir], [VDPAU_LIB_INSTALL_DIR='${libdir}/vdpau']) AC_SUBST([VDPAU_LIB_INSTALL_DIR]) -dnl Directory for OMX libs +dnl Directory for OMX_BELLAGIO libs -AC_ARG_WITH([omx-libdir], - [AS_HELP_STRING([--with-omx-libdir=DIR], - [directory for the OMX libraries])], - [OMX_LIB_INSTALL_DIR="$withval"], - [OMX_LIB_INSTALL_DIR=`$PKG_CONFIG --exists libomxil-bellagio && \ - $PKG_CONFIG --define-variable=libdir=\$libdir --variable=pluginsdir libomxil-bellagio`]) -AC_SUBST([OMX_LIB_INSTALL_DIR]) +AC_ARG_WITH([omx-bellagio-libdir], + [AS_HELP_STRING([--with-omx-bellagio-libdir=DIR], + [directory for the OMX_BELLAGIO libraries])], + [OMX_BELLAGIO_LIB_INSTALL_DIR="$withval"], + [OMX_BELLAGIO_LIB_INSTALL_DIR=`$PKG_CONFIG --exists libomxil-bellagio && \ + $PKG_CONFIG --define-variable=libdir=\$libdir --variable=pluginsdir libomxil-bellagio`]) +AC_SUBST([OMX_BELLAGIO_LIB_INSTALL_DIR]) dnl Directory for VA libs @@ -2852,7 +2857,7 @@ AC_CONFIG_FILES([Makefile src/gallium/state_trackers/dri/Makefile src/gallium/state_trackers/glx/xlib/Makefile src/gallium/state_trackers/nine/Makefile - src/gallium/state_trackers/omx/Makefile + src/gallium/state_trackers/omx_bellagio/Makefile src/gallium/state_trackers/osmesa/Makefile src/gallium/state_trackers/va/Makefile src/gallium/state_trackers/vdpau/Makefile @@ -2862,7 +2867,7 @@ AC_CONFIG_FILES([Makefile src/gallium/targets/d3dadapter9/d3d.pc src/gallium/targets/dri/Makefile src/gallium/targets/libgl-xlib/Makefile - src/gallium/targets/omx/Makefile + src/gallium/targets/omx-bellagio/Makefile src/gallium/targets/opencl/Makefile src/gallium/targets/opencl/mesa.icd src/gallium/targets/osmesa/Makefile diff --git a/src/gallium/Makefile.am b/src/gallium/Makefile.am index 9f98a7e28b6..2b930ac2cc1 100644 --- a/src/gallium/Makefile.am +++ b/src/gallium/Makefile.am @@ -149,8 +149,8 @@ if HAVE_GALLIUM_XLIB_GLX SUBDIRS += state_trackers/glx/xlib targets/libgl-xlib endif -if HAVE_ST_OMX -SUBDIRS += state_trackers/omx targets/omx +if HAVE_ST_OMX_BELLAGIO +SUBDIRS += state_trackers/omx_bellagio targets/omx-bellagio endif if HAVE_GALLIUM_OSMESA diff --git a/src/gallium/state_trackers/omx/Makefile.am b/src/gallium/state_trackers/omx/Makefile.am deleted file mode 100644 index e2d9ec72dc6..00000000000 --- a/src/gallium/state_trackers/omx/Makefile.am +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright © 2012 Intel Corporation -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice (including the next -# paragraph) shall be included in all copies or substantial portions of the -# Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. - -include Makefile.sources -include $(top_srcdir)/src/gallium/Automake.inc - -AM_CFLAGS = \ - $(GALLIUM_CFLAGS) \ - $(VISIBILITY_CFLAGS) \ - $(VL_CFLAGS) \ - $(XCB_DRI3_CFLAGS) \ - $(OMX_CFLAGS) - -noinst_LTLIBRARIES = libomxtracker.la - -libomxtracker_la_SOURCES = $(C_SOURCES) diff --git a/src/gallium/state_trackers/omx/Makefile.sources b/src/gallium/state_trackers/omx/Makefile.sources deleted file mode 100644 index ab60ce803cb..00000000000 --- a/src/gallium/state_trackers/omx/Makefile.sources +++ /dev/null @@ -1,10 +0,0 @@ -C_SOURCES := \ - entrypoint.c \ - entrypoint.h \ - vid_dec.c \ - vid_dec.h \ - vid_dec_mpeg12.c \ - vid_dec_h264.c \ - vid_dec_h265.c \ - vid_enc.c \ - vid_enc.h diff --git a/src/gallium/state_trackers/omx/entrypoint.c b/src/gallium/state_trackers/omx/entrypoint.c deleted file mode 100644 index 251cc7d65d5..00000000000 --- a/src/gallium/state_trackers/omx/entrypoint.c +++ /dev/null @@ -1,152 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* - * Authors: - * Christian König - * - */ - -#include -#include -#include - -#if defined(HAVE_X11_PLATFORM) -#include -#else -#define XOpenDisplay(x) NULL -#define XCloseDisplay(x) -#define Display void -#endif - -#include "os/os_thread.h" -#include "util/u_memory.h" -#include "loader/loader.h" - -#include "entrypoint.h" -#include "vid_dec.h" -#include "vid_enc.h" - -static mtx_t omx_lock = _MTX_INITIALIZER_NP; -static Display *omx_display = NULL; -static struct vl_screen *omx_screen = NULL; -static unsigned omx_usecount = 0; -static const char *omx_render_node = NULL; -static int drm_fd; - -int omx_component_library_Setup(stLoaderComponentType **stComponents) -{ - OMX_ERRORTYPE r; - - if (stComponents == NULL) - return 2; - - /* component 0 - video decoder */ - r = vid_dec_LoaderComponent(stComponents[0]); - if (r != OMX_ErrorNone) - return OMX_ErrorInsufficientResources; - - /* component 1 - video encoder */ - r = vid_enc_LoaderComponent(stComponents[1]); - if (r != OMX_ErrorNone) - return OMX_ErrorInsufficientResources; - - return 2; -} - -struct vl_screen *omx_get_screen(void) -{ - static bool first_time = true; - mtx_lock(&omx_lock); - - if (!omx_screen) { - if (first_time) { - omx_render_node = debug_get_option("OMX_RENDER_NODE", NULL); - first_time = false; - } - if (omx_render_node) { - drm_fd = loader_open_device(omx_render_node); - if (drm_fd < 0) - goto error; - - omx_screen = vl_drm_screen_create(drm_fd); - if (!omx_screen) { - close(drm_fd); - goto error; - } - } else { - omx_display = XOpenDisplay(NULL); - if (!omx_display) - goto error; - - omx_screen = vl_dri3_screen_create(omx_display, 0); - if (!omx_screen) - omx_screen = vl_dri2_screen_create(omx_display, 0); - if (!omx_screen) { - XCloseDisplay(omx_display); - goto error; - } - } - } - - ++omx_usecount; - - mtx_unlock(&omx_lock); - return omx_screen; - -error: - mtx_unlock(&omx_lock); - return NULL; -} - -void omx_put_screen(void) -{ - mtx_lock(&omx_lock); - if ((--omx_usecount) == 0) { - omx_screen->destroy(omx_screen); - omx_screen = NULL; - - if (omx_render_node) - close(drm_fd); - else - XCloseDisplay(omx_display); - } - mtx_unlock(&omx_lock); -} - -OMX_ERRORTYPE omx_workaround_Destructor(OMX_COMPONENTTYPE *comp) -{ - omx_base_component_PrivateType* priv = (omx_base_component_PrivateType*)comp->pComponentPrivate; - - priv->state = OMX_StateInvalid; - tsem_up(priv->messageSem); - - /* wait for thread to exit */ - pthread_join(priv->messageHandlerThread, NULL); - - return omx_base_component_Destructor(comp); -} diff --git a/src/gallium/state_trackers/omx/entrypoint.h b/src/gallium/state_trackers/omx/entrypoint.h deleted file mode 100644 index 7625d7a5b03..00000000000 --- a/src/gallium/state_trackers/omx/entrypoint.h +++ /dev/null @@ -1,48 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* - * Authors: - * Christian König - * - */ - -#ifndef OMX_ENTRYPOINT_H -#define OMX_ENTRYPOINT_H - -#include - -#include "vl/vl_winsys.h" - -PUBLIC extern int omx_component_library_Setup(stLoaderComponentType **stComponents); - -struct vl_screen *omx_get_screen(void); -void omx_put_screen(void); - -OMX_ERRORTYPE omx_workaround_Destructor(OMX_COMPONENTTYPE *comp); - -#endif diff --git a/src/gallium/state_trackers/omx/vid_dec.c b/src/gallium/state_trackers/omx/vid_dec.c deleted file mode 100644 index 28741c09a42..00000000000 --- a/src/gallium/state_trackers/omx/vid_dec.c +++ /dev/null @@ -1,637 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* - * Authors: - * Christian König - * - */ - - -#include - -#include - -/* bellagio defines a DEBUG macro that we don't want */ -#ifndef DEBUG -#include -#undef DEBUG -#else -#include -#endif - -#include "pipe/p_screen.h" -#include "pipe/p_video_codec.h" -#include "util/u_memory.h" -#include "util/u_surface.h" -#include "vl/vl_video_buffer.h" -#include "vl/vl_vlc.h" - -#include "entrypoint.h" -#include "vid_dec.h" - -static OMX_ERRORTYPE vid_dec_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name); -static OMX_ERRORTYPE vid_dec_Destructor(OMX_COMPONENTTYPE *comp); -static OMX_ERRORTYPE vid_dec_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param); -static OMX_ERRORTYPE vid_dec_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param); -static OMX_ERRORTYPE vid_dec_MessageHandler(OMX_COMPONENTTYPE *comp, internalRequestMessageType *msg); -static OMX_ERRORTYPE vid_dec_DecodeBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf); -static OMX_ERRORTYPE vid_dec_FreeDecBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf); -static void vid_dec_FrameDecoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output); - -OMX_ERRORTYPE vid_dec_LoaderComponent(stLoaderComponentType *comp) -{ - comp->componentVersion.s.nVersionMajor = 0; - comp->componentVersion.s.nVersionMinor = 0; - comp->componentVersion.s.nRevision = 0; - comp->componentVersion.s.nStep = 1; - comp->name_specific_length = 3; - - comp->name = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); - if (comp->name == NULL) - goto error; - - comp->name_specific = CALLOC(comp->name_specific_length, sizeof(char *)); - if (comp->name_specific == NULL) - goto error; - - comp->role_specific = CALLOC(comp->name_specific_length, sizeof(char *)); - if (comp->role_specific == NULL) - goto error; - - comp->name_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); - if (comp->name_specific[0] == NULL) - goto error_specific; - - comp->name_specific[1] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); - if (comp->name_specific[1] == NULL) - goto error_specific; - - comp->name_specific[2] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); - if (comp->name_specific[2] == NULL) - goto error_specific; - - comp->role_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); - if (comp->role_specific[0] == NULL) - goto error_specific; - - comp->role_specific[1] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); - if (comp->role_specific[1] == NULL) - goto error_specific; - - comp->role_specific[2] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); - if (comp->role_specific[2] == NULL) - goto error_specific; - - strcpy(comp->name, OMX_VID_DEC_BASE_NAME); - strcpy(comp->name_specific[0], OMX_VID_DEC_MPEG2_NAME); - strcpy(comp->name_specific[1], OMX_VID_DEC_AVC_NAME); - strcpy(comp->name_specific[2], OMX_VID_DEC_HEVC_NAME); - - strcpy(comp->role_specific[0], OMX_VID_DEC_MPEG2_ROLE); - strcpy(comp->role_specific[1], OMX_VID_DEC_AVC_ROLE); - strcpy(comp->role_specific[2], OMX_VID_DEC_HEVC_ROLE); - - comp->constructor = vid_dec_Constructor; - - return OMX_ErrorNone; - -error_specific: - FREE(comp->role_specific[2]); - FREE(comp->role_specific[1]); - FREE(comp->role_specific[0]); - FREE(comp->name_specific[2]); - FREE(comp->name_specific[1]); - FREE(comp->name_specific[0]); - -error: - FREE(comp->role_specific); - FREE(comp->name_specific); - - FREE(comp->name); - - return OMX_ErrorInsufficientResources; -} - -static OMX_ERRORTYPE vid_dec_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name) -{ - vid_dec_PrivateType *priv; - omx_base_video_PortType *port; - struct pipe_screen *screen; - OMX_ERRORTYPE r; - int i; - - assert(!comp->pComponentPrivate); - - priv = comp->pComponentPrivate = CALLOC(1, sizeof(vid_dec_PrivateType)); - if (!priv) - return OMX_ErrorInsufficientResources; - - r = omx_base_filter_Constructor(comp, name); - if (r) - return r; - - priv->profile = PIPE_VIDEO_PROFILE_UNKNOWN; - - if (!strcmp(name, OMX_VID_DEC_MPEG2_NAME)) - priv->profile = PIPE_VIDEO_PROFILE_MPEG2_MAIN; - - if (!strcmp(name, OMX_VID_DEC_AVC_NAME)) - priv->profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; - - if (!strcmp(name, OMX_VID_DEC_HEVC_NAME)) - priv->profile = PIPE_VIDEO_PROFILE_HEVC_MAIN; - - priv->BufferMgmtCallback = vid_dec_FrameDecoded; - priv->messageHandler = vid_dec_MessageHandler; - priv->destructor = vid_dec_Destructor; - - comp->SetParameter = vid_dec_SetParameter; - comp->GetParameter = vid_dec_GetParameter; - - priv->screen = omx_get_screen(); - if (!priv->screen) - return OMX_ErrorInsufficientResources; - - screen = priv->screen->pscreen; - priv->pipe = screen->context_create(screen, NULL, 0); - if (!priv->pipe) - return OMX_ErrorInsufficientResources; - - if (!vl_compositor_init(&priv->compositor, priv->pipe)) { - priv->pipe->destroy(priv->pipe); - priv->pipe = NULL; - return OMX_ErrorInsufficientResources; - } - - if (!vl_compositor_init_state(&priv->cstate, priv->pipe)) { - vl_compositor_cleanup(&priv->compositor); - priv->pipe->destroy(priv->pipe); - priv->pipe = NULL; - return OMX_ErrorInsufficientResources; - } - - priv->sPortTypesParam[OMX_PortDomainVideo].nStartPortNumber = 0; - priv->sPortTypesParam[OMX_PortDomainVideo].nPorts = 2; - priv->ports = CALLOC(2, sizeof(omx_base_PortType *)); - if (!priv->ports) - return OMX_ErrorInsufficientResources; - - for (i = 0; i < 2; ++i) { - priv->ports[i] = CALLOC(1, sizeof(omx_base_video_PortType)); - if (!priv->ports[i]) - return OMX_ErrorInsufficientResources; - - base_video_port_Constructor(comp, &priv->ports[i], i, i == 0); - } - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; - strcpy(port->sPortParam.format.video.cMIMEType,"video/MPEG2"); - port->sPortParam.nBufferCountMin = 8; - port->sPortParam.nBufferCountActual = 8; - port->sPortParam.nBufferSize = DEFAULT_OUT_BUFFER_SIZE; - port->sPortParam.format.video.nFrameWidth = 176; - port->sPortParam.format.video.nFrameHeight = 144; - port->sPortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG2; - port->sVideoParam.eCompressionFormat = OMX_VIDEO_CodingMPEG2; - port->Port_SendBufferFunction = vid_dec_DecodeBuffer; - port->Port_FreeBuffer = vid_dec_FreeDecBuffer; - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; - port->sPortParam.nBufferCountActual = 8; - port->sPortParam.nBufferCountMin = 4; - port->sPortParam.format.video.nFrameWidth = 176; - port->sPortParam.format.video.nFrameHeight = 144; - port->sPortParam.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; - port->sVideoParam.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_dec_Destructor(OMX_COMPONENTTYPE *comp) -{ - vid_dec_PrivateType* priv = comp->pComponentPrivate; - int i; - - if (priv->ports) { - for (i = 0; i < priv->sPortTypesParam[OMX_PortDomainVideo].nPorts; ++i) { - if(priv->ports[i]) - priv->ports[i]->PortDestructor(priv->ports[i]); - } - FREE(priv->ports); - priv->ports=NULL; - } - - if (priv->pipe) { - vl_compositor_cleanup_state(&priv->cstate); - vl_compositor_cleanup(&priv->compositor); - priv->pipe->destroy(priv->pipe); - } - - if (priv->screen) - omx_put_screen(); - - return omx_workaround_Destructor(comp); -} - -static OMX_ERRORTYPE vid_dec_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param) -{ - OMX_COMPONENTTYPE *comp = handle; - vid_dec_PrivateType *priv = comp->pComponentPrivate; - OMX_ERRORTYPE r; - - if (!param) - return OMX_ErrorBadParameter; - - switch(idx) { - case OMX_IndexParamPortDefinition: { - OMX_PARAM_PORTDEFINITIONTYPE *def = param; - - r = omx_base_component_SetParameter(handle, idx, param); - if (r) - return r; - - if (def->nPortIndex == OMX_BASE_FILTER_INPUTPORT_INDEX) { - omx_base_video_PortType *port; - unsigned framesize = def->format.video.nFrameWidth * def->format.video.nFrameHeight; - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; - port->sPortParam.nBufferSize = framesize * 512 / (16*16); - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; - port->sPortParam.format.video.nFrameWidth = def->format.video.nFrameWidth; - port->sPortParam.format.video.nFrameHeight = def->format.video.nFrameHeight; - port->sPortParam.format.video.nStride = def->format.video.nFrameWidth; - port->sPortParam.format.video.nSliceHeight = def->format.video.nFrameHeight; - port->sPortParam.nBufferSize = framesize*3/2; - - priv->callbacks->EventHandler(comp, priv->callbackData, OMX_EventPortSettingsChanged, - OMX_BASE_FILTER_OUTPUTPORT_INDEX, 0, NULL); - } - break; - } - case OMX_IndexParamStandardComponentRole: { - OMX_PARAM_COMPONENTROLETYPE *role = param; - - r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE)); - if (r) - return r; - - if (!strcmp((char *)role->cRole, OMX_VID_DEC_MPEG2_ROLE)) { - priv->profile = PIPE_VIDEO_PROFILE_MPEG2_MAIN; - } else if (!strcmp((char *)role->cRole, OMX_VID_DEC_AVC_ROLE)) { - priv->profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; - } else if (!strcmp((char *)role->cRole, OMX_VID_DEC_HEVC_ROLE)) { - priv->profile = PIPE_VIDEO_PROFILE_HEVC_MAIN; - } else { - return OMX_ErrorBadParameter; - } - - break; - } - case OMX_IndexParamVideoPortFormat: { - OMX_VIDEO_PARAM_PORTFORMATTYPE *format = param; - omx_base_video_PortType *port; - - r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); - if (r) - return r; - - if (format->nPortIndex > 1) - return OMX_ErrorBadPortIndex; - - port = (omx_base_video_PortType *)priv->ports[format->nPortIndex]; - memcpy(&port->sVideoParam, format, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); - break; - } - default: - return omx_base_component_SetParameter(handle, idx, param); - } - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_dec_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param) -{ - OMX_COMPONENTTYPE *comp = handle; - vid_dec_PrivateType *priv = comp->pComponentPrivate; - OMX_ERRORTYPE r; - - if (!param) - return OMX_ErrorBadParameter; - - switch(idx) { - case OMX_IndexParamStandardComponentRole: { - OMX_PARAM_COMPONENTROLETYPE *role = param; - - r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE)); - if (r) - return r; - - if (priv->profile == PIPE_VIDEO_PROFILE_MPEG2_MAIN) - strcpy((char *)role->cRole, OMX_VID_DEC_MPEG2_ROLE); - else if (priv->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH) - strcpy((char *)role->cRole, OMX_VID_DEC_AVC_ROLE); - else if (priv->profile == PIPE_VIDEO_PROFILE_HEVC_MAIN) - strcpy((char *)role->cRole, OMX_VID_DEC_HEVC_ROLE); - - break; - } - - case OMX_IndexParamVideoInit: - r = checkHeader(param, sizeof(OMX_PORT_PARAM_TYPE)); - if (r) - return r; - - memcpy(param, &priv->sPortTypesParam[OMX_PortDomainVideo], sizeof(OMX_PORT_PARAM_TYPE)); - break; - - case OMX_IndexParamVideoPortFormat: { - OMX_VIDEO_PARAM_PORTFORMATTYPE *format = param; - omx_base_video_PortType *port; - - r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); - if (r) - return r; - - if (format->nPortIndex > 1) - return OMX_ErrorBadPortIndex; - - port = (omx_base_video_PortType *)priv->ports[format->nPortIndex]; - memcpy(format, &port->sVideoParam, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); - break; - } - - default: - return omx_base_component_GetParameter(handle, idx, param); - - } - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_dec_MessageHandler(OMX_COMPONENTTYPE* comp, internalRequestMessageType *msg) -{ - vid_dec_PrivateType* priv = comp->pComponentPrivate; - - if (msg->messageType == OMX_CommandStateSet) { - if ((msg->messageParam == OMX_StateIdle ) && (priv->state == OMX_StateLoaded)) { - if (priv->profile == PIPE_VIDEO_PROFILE_MPEG2_MAIN) - vid_dec_mpeg12_Init(priv); - else if (priv->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH) - vid_dec_h264_Init(priv); - else if (priv->profile == PIPE_VIDEO_PROFILE_HEVC_MAIN) - vid_dec_h265_Init(priv); - - } else if ((msg->messageParam == OMX_StateLoaded) && (priv->state == OMX_StateIdle)) { - if (priv->shadow) { - priv->shadow->destroy(priv->shadow); - priv->shadow = NULL; - } - if (priv->codec) { - priv->codec->destroy(priv->codec); - priv->codec = NULL; - } - } - } - - return omx_base_component_MessageHandler(comp, msg); -} - -void vid_dec_NeedTarget(vid_dec_PrivateType *priv) -{ - struct pipe_video_buffer templat = {}; - struct vl_screen *omx_screen; - struct pipe_screen *pscreen; - - omx_screen = priv->screen; - assert(omx_screen); - - pscreen = omx_screen->pscreen; - assert(pscreen); - - if (!priv->target) { - memset(&templat, 0, sizeof(templat)); - - templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - templat.width = priv->codec->width; - templat.height = priv->codec->height; - templat.buffer_format = pscreen->get_video_param( - pscreen, - PIPE_VIDEO_PROFILE_UNKNOWN, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_PREFERED_FORMAT - ); - templat.interlaced = pscreen->get_video_param( - pscreen, - PIPE_VIDEO_PROFILE_UNKNOWN, - PIPE_VIDEO_ENTRYPOINT_BITSTREAM, - PIPE_VIDEO_CAP_PREFERS_INTERLACED - ); - priv->target = priv->pipe->create_video_buffer(priv->pipe, &templat); - } -} - -static void vid_dec_FreeInputPortPrivate(OMX_BUFFERHEADERTYPE *buf) -{ - struct pipe_video_buffer *vbuf = buf->pInputPortPrivate; - if (!vbuf) - return; - - vbuf->destroy(vbuf); - buf->pInputPortPrivate = NULL; -} - -static OMX_ERRORTYPE vid_dec_DecodeBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf) -{ - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_dec_PrivateType *priv = comp->pComponentPrivate; - unsigned i = priv->num_in_buffers++; - OMX_ERRORTYPE r; - - priv->in_buffers[i] = buf; - priv->sizes[i] = buf->nFilledLen; - priv->inputs[i] = buf->pBuffer; - priv->timestamps[i] = buf->nTimeStamp; - - while (priv->num_in_buffers > (!!(buf->nFlags & OMX_BUFFERFLAG_EOS) ? 0 : 1)) { - bool eos = !!(priv->in_buffers[0]->nFlags & OMX_BUFFERFLAG_EOS); - unsigned min_bits_left = eos ? 32 : MAX2(buf->nFilledLen * 8, 32); - struct vl_vlc vlc; - - vl_vlc_init(&vlc, priv->num_in_buffers, priv->inputs, priv->sizes); - - if (priv->slice) - priv->bytes_left = vl_vlc_bits_left(&vlc) / 8; - - while (vl_vlc_bits_left(&vlc) > min_bits_left) { - priv->Decode(priv, &vlc, min_bits_left); - vl_vlc_fillbits(&vlc); - } - - if (priv->slice) { - unsigned bytes = priv->bytes_left - vl_vlc_bits_left(&vlc) / 8; - - priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, - 1, &priv->slice, &bytes); - - if (priv->num_in_buffers) - priv->slice = priv->inputs[1]; - else - priv->slice = NULL; - } - - if (eos && priv->frame_started) - priv->EndFrame(priv); - - if (priv->frame_finished) { - priv->frame_finished = false; - priv->in_buffers[0]->nFilledLen = priv->in_buffers[0]->nAllocLen; - r = base_port_SendBufferFunction(port, priv->in_buffers[0]); - } else if (eos) { - vid_dec_FreeInputPortPrivate(priv->in_buffers[0]); - priv->in_buffers[0]->nFilledLen = priv->in_buffers[0]->nAllocLen; - r = base_port_SendBufferFunction(port, priv->in_buffers[0]); - } else { - priv->in_buffers[0]->nFilledLen = 0; - r = port->ReturnBufferFunction(port, priv->in_buffers[0]); - } - - if (--priv->num_in_buffers) { - unsigned delta = MIN2((min_bits_left - vl_vlc_bits_left(&vlc)) / 8, priv->sizes[1]); - - priv->in_buffers[0] = priv->in_buffers[1]; - priv->sizes[0] = priv->sizes[1] - delta; - priv->inputs[0] = priv->inputs[1] + delta; - priv->timestamps[0] = priv->timestamps[1]; - } - - if (r) - return r; - } - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_dec_FreeDecBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf) -{ - vid_dec_FreeInputPortPrivate(buf); - return base_port_FreeBuffer(port, idx, buf); -} - -static void vid_dec_FillOutput(vid_dec_PrivateType *priv, struct pipe_video_buffer *buf, - OMX_BUFFERHEADERTYPE* output) -{ - omx_base_PortType *port = priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; - OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; - - struct pipe_sampler_view **views; - unsigned i, j; - unsigned width, height; - - views = buf->get_sampler_view_planes(buf); - - for (i = 0; i < 2 /* NV12 */; i++) { - if (!views[i]) continue; - width = def->nFrameWidth; - height = def->nFrameHeight; - vl_video_buffer_adjust_size(&width, &height, i, buf->chroma_format, buf->interlaced); - for (j = 0; j < views[i]->texture->array_size; ++j) { - struct pipe_box box = {0, 0, j, width, height, 1}; - struct pipe_transfer *transfer; - uint8_t *map, *dst; - map = priv->pipe->transfer_map(priv->pipe, views[i]->texture, 0, - PIPE_TRANSFER_READ, &box, &transfer); - if (!map) - return; - - dst = ((uint8_t*)output->pBuffer + output->nOffset) + j * def->nStride + - i * def->nFrameWidth * def->nFrameHeight; - util_copy_rect(dst, - views[i]->texture->format, - def->nStride * views[i]->texture->array_size, 0, 0, - box.width, box.height, map, transfer->stride, 0, 0); - - pipe_transfer_unmap(priv->pipe, transfer); - } - } -} - -static void vid_dec_FrameDecoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, - OMX_BUFFERHEADERTYPE* output) -{ - vid_dec_PrivateType *priv = comp->pComponentPrivate; - bool eos = !!(input->nFlags & OMX_BUFFERFLAG_EOS); - OMX_TICKS timestamp; - - if (!input->pInputPortPrivate) { - input->pInputPortPrivate = priv->Flush(priv, ×tamp); - if (timestamp != OMX_VID_DEC_TIMESTAMP_INVALID) - input->nTimeStamp = timestamp; - } - - if (input->pInputPortPrivate) { - if (output->pInputPortPrivate && !priv->disable_tunnel) { - struct pipe_video_buffer *tmp, *vbuf, *new_vbuf; - - tmp = output->pOutputPortPrivate; - vbuf = input->pInputPortPrivate; - if (vbuf->interlaced) { - /* re-allocate the progressive buffer */ - omx_base_video_PortType *port; - struct pipe_video_buffer templat = {}; - - port = (omx_base_video_PortType *) - priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; - memset(&templat, 0, sizeof(templat)); - templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - templat.width = port->sPortParam.format.video.nFrameWidth; - templat.height = port->sPortParam.format.video.nFrameHeight; - templat.buffer_format = PIPE_FORMAT_NV12; - templat.interlaced = false; - new_vbuf = priv->pipe->create_video_buffer(priv->pipe, &templat); - - /* convert the interlaced to the progressive */ - vl_compositor_yuv_deint(&priv->cstate, &priv->compositor, - input->pInputPortPrivate, new_vbuf); - - /* set the progrssive buffer for next round */ - vbuf->destroy(vbuf); - input->pInputPortPrivate = new_vbuf; - } - output->pOutputPortPrivate = input->pInputPortPrivate; - input->pInputPortPrivate = tmp; - } else { - vid_dec_FillOutput(priv, input->pInputPortPrivate, output); - } - output->nFilledLen = output->nAllocLen; - output->nTimeStamp = input->nTimeStamp; - } - - if (eos && input->pInputPortPrivate) - vid_dec_FreeInputPortPrivate(input); - else - input->nFilledLen = 0; -} diff --git a/src/gallium/state_trackers/omx/vid_dec.h b/src/gallium/state_trackers/omx/vid_dec.h deleted file mode 100644 index 7a10e750d91..00000000000 --- a/src/gallium/state_trackers/omx/vid_dec.h +++ /dev/null @@ -1,148 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* - * Authors: - * Christian König - * - */ - -#ifndef OMX_VID_DEC_H -#define OMX_VID_DEC_H - -#include - -#include -#include -#include - -#include -#include -#include - -#include "pipe/p_video_state.h" -#include "os/os_thread.h" -#include "util/list.h" - -#include "vl/vl_compositor.h" - -#define OMX_VID_DEC_BASE_NAME "OMX.mesa.video_decoder" - -#define OMX_VID_DEC_MPEG2_NAME "OMX.mesa.video_decoder.mpeg2" -#define OMX_VID_DEC_MPEG2_ROLE "video_decoder.mpeg2" - -#define OMX_VID_DEC_AVC_NAME "OMX.mesa.video_decoder.avc" -#define OMX_VID_DEC_AVC_ROLE "video_decoder.avc" - -#define OMX_VID_DEC_HEVC_NAME "OMX.mesa.video_decoder.hevc" -#define OMX_VID_DEC_HEVC_ROLE "video_decoder.hevc" - -#define OMX_VID_DEC_TIMESTAMP_INVALID ((OMX_TICKS) -1) - -struct vl_vlc; - -DERIVEDCLASS(vid_dec_PrivateType, omx_base_filter_PrivateType) -#define vid_dec_PrivateType_FIELDS omx_base_filter_PrivateType_FIELDS \ - enum pipe_video_profile profile; \ - struct vl_screen *screen; \ - struct pipe_context *pipe; \ - struct pipe_video_codec *codec; \ - void (*Decode)(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left); \ - void (*EndFrame)(vid_dec_PrivateType *priv); \ - struct pipe_video_buffer *(*Flush)(vid_dec_PrivateType *priv, OMX_TICKS *timestamp); \ - struct pipe_video_buffer *target, *shadow; \ - union { \ - struct { \ - uint8_t intra_matrix[64]; \ - uint8_t non_intra_matrix[64]; \ - } mpeg12; \ - struct { \ - unsigned nal_ref_idc; \ - bool IdrPicFlag; \ - unsigned idr_pic_id; \ - unsigned pic_order_cnt_lsb; \ - unsigned pic_order_cnt_msb; \ - unsigned delta_pic_order_cnt_bottom; \ - unsigned delta_pic_order_cnt[2]; \ - unsigned prevFrameNumOffset; \ - struct pipe_h264_sps sps[32]; \ - struct pipe_h264_pps pps[256]; \ - struct list_head dpb_list; \ - unsigned dpb_num; \ - } h264; \ - struct { \ - unsigned temporal_id; \ - unsigned level_idc; \ - unsigned pic_width_in_luma_samples; \ - unsigned pic_height_in_luma_samples; \ - bool IdrPicFlag; \ - int slice_prev_poc; \ - void *ref_pic_set_list; \ - void *rps; \ - struct pipe_h265_sps sps[16]; \ - struct pipe_h265_pps pps[64]; \ - struct list_head dpb_list; \ - unsigned dpb_num; \ - } h265; \ - } codec_data; \ - union { \ - struct pipe_picture_desc base; \ - struct pipe_mpeg12_picture_desc mpeg12; \ - struct pipe_h264_picture_desc h264; \ - struct pipe_h265_picture_desc h265; \ - } picture; \ - unsigned num_in_buffers; \ - OMX_BUFFERHEADERTYPE *in_buffers[2]; \ - const void *inputs[2]; \ - unsigned sizes[2]; \ - OMX_TICKS timestamps[2]; \ - OMX_TICKS timestamp; \ - bool first_buf_in_frame; \ - bool frame_finished; \ - bool frame_started; \ - unsigned bytes_left; \ - const void *slice; \ - bool disable_tunnel; \ - struct vl_compositor compositor; \ - struct vl_compositor_state cstate; -ENDCLASS(vid_dec_PrivateType) - -OMX_ERRORTYPE vid_dec_LoaderComponent(stLoaderComponentType *comp); - -/* used by MPEG12 and H264 implementation */ -void vid_dec_NeedTarget(vid_dec_PrivateType *priv); - -/* vid_dec_mpeg12.c */ -void vid_dec_mpeg12_Init(vid_dec_PrivateType *priv); - -/* vid_dec_h264.c */ -void vid_dec_h264_Init(vid_dec_PrivateType *priv); - -/* vid_dec_h265.c */ -void vid_dec_h265_Init(vid_dec_PrivateType *priv); - -#endif diff --git a/src/gallium/state_trackers/omx/vid_dec_h264.c b/src/gallium/state_trackers/omx/vid_dec_h264.c deleted file mode 100644 index 7ea71c1046b..00000000000 --- a/src/gallium/state_trackers/omx/vid_dec_h264.c +++ /dev/null @@ -1,1032 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* - * Authors: - * Christian König - * - */ - -#include "pipe/p_video_codec.h" -#include "util/u_memory.h" -#include "util/u_video.h" -#include "vl/vl_rbsp.h" -#include "vl/vl_zscan.h" - -#include "entrypoint.h" -#include "vid_dec.h" - -#define DPB_MAX_SIZE 5 - -struct dpb_list { - struct list_head list; - struct pipe_video_buffer *buffer; - OMX_TICKS timestamp; - int poc; -}; - -static const uint8_t Default_4x4_Intra[16] = { - 6, 13, 20, 28, 13, 20, 28, 32, - 20, 28, 32, 37, 28, 32, 37, 42 -}; - -static const uint8_t Default_4x4_Inter[16] = { - 10, 14, 20, 24, 14, 20, 24, 27, - 20, 24, 27, 30, 24, 27, 30, 34 -}; - -static const uint8_t Default_8x8_Intra[64] = { - 6, 10, 13, 16, 18, 23, 25, 27, - 10, 11, 16, 18, 23, 25, 27, 29, - 13, 16, 18, 23, 25, 27, 29, 31, - 16, 18, 23, 25, 27, 29, 31, 33, - 18, 23, 25, 27, 29, 31, 33, 36, - 23, 25, 27, 29, 31, 33, 36, 38, - 25, 27, 29, 31, 33, 36, 38, 40, - 27, 29, 31, 33, 36, 38, 40, 42 -}; - -static const uint8_t Default_8x8_Inter[64] = { - 9, 13, 15, 17, 19, 21, 22, 24, - 13, 13, 17, 19, 21, 22, 24, 25, - 15, 17, 19, 21, 22, 24, 25, 27, - 17, 19, 21, 22, 24, 25, 27, 28, - 19, 21, 22, 24, 25, 27, 28, 30, - 21, 22, 24, 25, 27, 28, 30, 32, - 22, 24, 25, 27, 28, 30, 32, 33, - 24, 25, 27, 28, 30, 32, 33, 35 -}; - -static void vid_dec_h264_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left); -static void vid_dec_h264_EndFrame(vid_dec_PrivateType *priv); -static struct pipe_video_buffer *vid_dec_h264_Flush(vid_dec_PrivateType *priv, OMX_TICKS *timestamp); - -void vid_dec_h264_Init(vid_dec_PrivateType *priv) -{ - priv->picture.base.profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; - - priv->Decode = vid_dec_h264_Decode; - priv->EndFrame = vid_dec_h264_EndFrame; - priv->Flush = vid_dec_h264_Flush; - - LIST_INITHEAD(&priv->codec_data.h264.dpb_list); - priv->picture.h264.field_order_cnt[0] = priv->picture.h264.field_order_cnt[1] = INT_MAX; - priv->first_buf_in_frame = true; -} - -static void vid_dec_h264_BeginFrame(vid_dec_PrivateType *priv) -{ - //TODO: sane buffer handling - - if (priv->frame_started) - return; - - if (!priv->codec) { - struct pipe_video_codec templat = {}; - omx_base_video_PortType *port; - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; - templat.profile = priv->profile; - templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; - templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - templat.max_references = priv->picture.h264.num_ref_frames; - templat.expect_chunked_decode = true; - templat.width = port->sPortParam.format.video.nFrameWidth; - templat.height = port->sPortParam.format.video.nFrameHeight; - templat.level = priv->picture.h264.pps->sps->level_idc; - - priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat); - } - - vid_dec_NeedTarget(priv); - - if (priv->first_buf_in_frame) - priv->timestamp = priv->timestamps[0]; - priv->first_buf_in_frame = false; - - priv->picture.h264.num_ref_frames = priv->picture.h264.pps->sps->max_num_ref_frames; - - priv->picture.h264.slice_count = 0; - priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base); - priv->frame_started = true; -} - -static struct pipe_video_buffer *vid_dec_h264_Flush(vid_dec_PrivateType *priv, - OMX_TICKS *timestamp) -{ - struct dpb_list *entry, *result = NULL; - struct pipe_video_buffer *buf; - - /* search for the lowest poc and break on zeros */ - LIST_FOR_EACH_ENTRY(entry, &priv->codec_data.h264.dpb_list, list) { - - if (result && entry->poc == 0) - break; - - if (!result || entry->poc < result->poc) - result = entry; - } - - if (!result) - return NULL; - - buf = result->buffer; - if (timestamp) - *timestamp = result->timestamp; - - --priv->codec_data.h264.dpb_num; - LIST_DEL(&result->list); - FREE(result); - - return buf; -} - -static void vid_dec_h264_EndFrame(vid_dec_PrivateType *priv) -{ - struct dpb_list *entry; - struct pipe_video_buffer *tmp; - bool top_field_first; - OMX_TICKS timestamp; - - if (!priv->frame_started) - return; - - priv->codec->end_frame(priv->codec, priv->target, &priv->picture.base); - priv->frame_started = false; - - // TODO: implement frame number handling - priv->picture.h264.frame_num_list[0] = priv->picture.h264.frame_num; - priv->picture.h264.field_order_cnt_list[0][0] = priv->picture.h264.frame_num; - priv->picture.h264.field_order_cnt_list[0][1] = priv->picture.h264.frame_num; - - top_field_first = priv->picture.h264.field_order_cnt[0] < priv->picture.h264.field_order_cnt[1]; - - if (priv->picture.h264.field_pic_flag && priv->picture.h264.bottom_field_flag != top_field_first) - return; - - /* add the decoded picture to the dpb list */ - entry = CALLOC_STRUCT(dpb_list); - if (!entry) - return; - - priv->first_buf_in_frame = true; - entry->buffer = priv->target; - entry->timestamp = priv->timestamp; - entry->poc = MIN2(priv->picture.h264.field_order_cnt[0], priv->picture.h264.field_order_cnt[1]); - LIST_ADDTAIL(&entry->list, &priv->codec_data.h264.dpb_list); - ++priv->codec_data.h264.dpb_num; - priv->target = NULL; - priv->picture.h264.field_order_cnt[0] = priv->picture.h264.field_order_cnt[1] = INT_MAX; - - if (priv->codec_data.h264.dpb_num <= DPB_MAX_SIZE) - return; - - tmp = priv->in_buffers[0]->pInputPortPrivate; - priv->in_buffers[0]->pInputPortPrivate = vid_dec_h264_Flush(priv, ×tamp); - priv->in_buffers[0]->nTimeStamp = timestamp; - priv->target = tmp; - priv->frame_finished = priv->in_buffers[0]->pInputPortPrivate != NULL; -} - -static void vui_parameters(struct vl_rbsp *rbsp) -{ - // TODO -} - -static void scaling_list(struct vl_rbsp *rbsp, uint8_t *scalingList, unsigned sizeOfScalingList, - const uint8_t *defaultList, const uint8_t *fallbackList) -{ - unsigned lastScale = 8, nextScale = 8; - const int *list; - unsigned i; - - /* (pic|seq)_scaling_list_present_flag[i] */ - if (!vl_rbsp_u(rbsp, 1)) { - if (fallbackList) - memcpy(scalingList, fallbackList, sizeOfScalingList); - return; - } - - list = (sizeOfScalingList == 16) ? vl_zscan_normal_16 : vl_zscan_normal; - for (i = 0; i < sizeOfScalingList; ++i ) { - - if (nextScale != 0) { - signed delta_scale = vl_rbsp_se(rbsp); - nextScale = (lastScale + delta_scale + 256) % 256; - if (i == 0 && nextScale == 0) { - memcpy(scalingList, defaultList, sizeOfScalingList); - return; - } - } - scalingList[list[i]] = nextScale == 0 ? lastScale : nextScale; - lastScale = scalingList[list[i]]; - } -} - -static struct pipe_h264_sps *seq_parameter_set_id(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) -{ - unsigned id = vl_rbsp_ue(rbsp); - if (id >= ARRAY_SIZE(priv->codec_data.h264.sps)) - return NULL; /* invalid seq_parameter_set_id */ - - return &priv->codec_data.h264.sps[id]; -} - -static void seq_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) -{ - struct pipe_h264_sps *sps; - unsigned profile_idc, level_idc; - unsigned i; - - /* Sequence parameter set */ - profile_idc = vl_rbsp_u(rbsp, 8); - - /* constraint_set0_flag */ - vl_rbsp_u(rbsp, 1); - - /* constraint_set1_flag */ - vl_rbsp_u(rbsp, 1); - - /* constraint_set2_flag */ - vl_rbsp_u(rbsp, 1); - - /* constraint_set3_flag */ - vl_rbsp_u(rbsp, 1); - - /* constraint_set4_flag */ - vl_rbsp_u(rbsp, 1); - - /* constraint_set5_flag */ - vl_rbsp_u(rbsp, 1); - - /* reserved_zero_2bits */ - vl_rbsp_u(rbsp, 2); - - /* level_idc */ - level_idc = vl_rbsp_u(rbsp, 8); - - sps = seq_parameter_set_id(priv, rbsp); - if (!sps) - return; - - memset(sps, 0, sizeof(*sps)); - memset(sps->ScalingList4x4, 16, sizeof(sps->ScalingList4x4)); - memset(sps->ScalingList8x8, 16, sizeof(sps->ScalingList8x8)); - - sps->level_idc = level_idc; - - if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 244 || - profile_idc == 44 || profile_idc == 83 || profile_idc == 86 || profile_idc == 118 || - profile_idc == 128 || profile_idc == 138) { - - sps->chroma_format_idc = vl_rbsp_ue(rbsp); - - if (sps->chroma_format_idc == 3) - sps->separate_colour_plane_flag = vl_rbsp_u(rbsp, 1); - - sps->bit_depth_luma_minus8 = vl_rbsp_ue(rbsp); - - sps->bit_depth_chroma_minus8 = vl_rbsp_ue(rbsp); - - /* qpprime_y_zero_transform_bypass_flag */ - vl_rbsp_u(rbsp, 1); - - sps->seq_scaling_matrix_present_flag = vl_rbsp_u(rbsp, 1); - if (sps->seq_scaling_matrix_present_flag) { - - scaling_list(rbsp, sps->ScalingList4x4[0], 16, Default_4x4_Intra, Default_4x4_Intra); - scaling_list(rbsp, sps->ScalingList4x4[1], 16, Default_4x4_Intra, sps->ScalingList4x4[0]); - scaling_list(rbsp, sps->ScalingList4x4[2], 16, Default_4x4_Intra, sps->ScalingList4x4[1]); - scaling_list(rbsp, sps->ScalingList4x4[3], 16, Default_4x4_Inter, Default_4x4_Inter); - scaling_list(rbsp, sps->ScalingList4x4[4], 16, Default_4x4_Inter, sps->ScalingList4x4[3]); - scaling_list(rbsp, sps->ScalingList4x4[5], 16, Default_4x4_Inter, sps->ScalingList4x4[4]); - - scaling_list(rbsp, sps->ScalingList8x8[0], 64, Default_8x8_Intra, Default_8x8_Intra); - scaling_list(rbsp, sps->ScalingList8x8[1], 64, Default_8x8_Inter, Default_8x8_Inter); - if (sps->chroma_format_idc == 3) { - scaling_list(rbsp, sps->ScalingList8x8[2], 64, Default_8x8_Intra, sps->ScalingList8x8[0]); - scaling_list(rbsp, sps->ScalingList8x8[3], 64, Default_8x8_Inter, sps->ScalingList8x8[1]); - scaling_list(rbsp, sps->ScalingList8x8[4], 64, Default_8x8_Intra, sps->ScalingList8x8[2]); - scaling_list(rbsp, sps->ScalingList8x8[5], 64, Default_8x8_Inter, sps->ScalingList8x8[3]); - } - } - } else if (profile_idc == 183) - sps->chroma_format_idc = 0; - else - sps->chroma_format_idc = 1; - - sps->log2_max_frame_num_minus4 = vl_rbsp_ue(rbsp); - - sps->pic_order_cnt_type = vl_rbsp_ue(rbsp); - - if (sps->pic_order_cnt_type == 0) - sps->log2_max_pic_order_cnt_lsb_minus4 = vl_rbsp_ue(rbsp); - else if (sps->pic_order_cnt_type == 1) { - sps->delta_pic_order_always_zero_flag = vl_rbsp_u(rbsp, 1); - - sps->offset_for_non_ref_pic = vl_rbsp_se(rbsp); - - sps->offset_for_top_to_bottom_field = vl_rbsp_se(rbsp); - - sps->num_ref_frames_in_pic_order_cnt_cycle = vl_rbsp_ue(rbsp); - - for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) - sps->offset_for_ref_frame[i] = vl_rbsp_se(rbsp); - } - - sps->max_num_ref_frames = vl_rbsp_ue(rbsp); - - /* gaps_in_frame_num_value_allowed_flag */ - vl_rbsp_u(rbsp, 1); - - /* pic_width_in_mbs_minus1 */ - vl_rbsp_ue(rbsp); - - /* pic_height_in_map_units_minus1 */ - vl_rbsp_ue(rbsp); - - sps->frame_mbs_only_flag = vl_rbsp_u(rbsp, 1); - if (!sps->frame_mbs_only_flag) - sps->mb_adaptive_frame_field_flag = vl_rbsp_u(rbsp, 1); - - sps->direct_8x8_inference_flag = vl_rbsp_u(rbsp, 1); - - /* frame_cropping_flag */ - if (vl_rbsp_u(rbsp, 1)) { - /* frame_crop_left_offset */ - vl_rbsp_ue(rbsp); - - /* frame_crop_right_offset */ - vl_rbsp_ue(rbsp); - - /* frame_crop_top_offset */ - vl_rbsp_ue(rbsp); - - /* frame_crop_bottom_offset */ - vl_rbsp_ue(rbsp); - } - - /* vui_parameters_present_flag */ - if (vl_rbsp_u(rbsp, 1)) - vui_parameters(rbsp); -} - -static struct pipe_h264_pps *pic_parameter_set_id(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) -{ - unsigned id = vl_rbsp_ue(rbsp); - if (id >= ARRAY_SIZE(priv->codec_data.h264.pps)) - return NULL; /* invalid pic_parameter_set_id */ - - return &priv->codec_data.h264.pps[id]; -} - -static void picture_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) -{ - struct pipe_h264_sps *sps; - struct pipe_h264_pps *pps; - unsigned i; - - pps = pic_parameter_set_id(priv, rbsp); - if (!pps) - return; - - memset(pps, 0, sizeof(*pps)); - - sps = pps->sps = seq_parameter_set_id(priv, rbsp); - if (!sps) - return; - - memcpy(pps->ScalingList4x4, sps->ScalingList4x4, sizeof(pps->ScalingList4x4)); - memcpy(pps->ScalingList8x8, sps->ScalingList8x8, sizeof(pps->ScalingList8x8)); - - pps->entropy_coding_mode_flag = vl_rbsp_u(rbsp, 1); - - pps->bottom_field_pic_order_in_frame_present_flag = vl_rbsp_u(rbsp, 1); - - pps->num_slice_groups_minus1 = vl_rbsp_ue(rbsp); - if (pps->num_slice_groups_minus1 > 0) { - pps->slice_group_map_type = vl_rbsp_ue(rbsp); - - if (pps->slice_group_map_type == 0) { - - for (i = 0; i <= pps->num_slice_groups_minus1; ++i) - /* run_length_minus1[i] */ - vl_rbsp_ue(rbsp); - - } else if (pps->slice_group_map_type == 2) { - - for (i = 0; i <= pps->num_slice_groups_minus1; ++i) { - /* top_left[i] */ - vl_rbsp_ue(rbsp); - - /* bottom_right[i] */ - vl_rbsp_ue(rbsp); - } - - } else if (pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5) { - - /* slice_group_change_direction_flag */ - vl_rbsp_u(rbsp, 1); - - pps->slice_group_change_rate_minus1 = vl_rbsp_ue(rbsp); - - } else if (pps->slice_group_map_type == 6) { - - unsigned pic_size_in_map_units_minus1; - - pic_size_in_map_units_minus1 = vl_rbsp_ue(rbsp); - - for (i = 0; i <= pic_size_in_map_units_minus1; ++i) - /* slice_group_id[i] */ - vl_rbsp_u(rbsp, log2(pps->num_slice_groups_minus1 + 1)); - } - } - - pps->num_ref_idx_l0_default_active_minus1 = vl_rbsp_ue(rbsp); - - pps->num_ref_idx_l1_default_active_minus1 = vl_rbsp_ue(rbsp); - - pps->weighted_pred_flag = vl_rbsp_u(rbsp, 1); - - pps->weighted_bipred_idc = vl_rbsp_u(rbsp, 2); - - pps->pic_init_qp_minus26 = vl_rbsp_se(rbsp); - - /* pic_init_qs_minus26 */ - vl_rbsp_se(rbsp); - - pps->chroma_qp_index_offset = vl_rbsp_se(rbsp); - - pps->deblocking_filter_control_present_flag = vl_rbsp_u(rbsp, 1); - - pps->constrained_intra_pred_flag = vl_rbsp_u(rbsp, 1); - - pps->redundant_pic_cnt_present_flag = vl_rbsp_u(rbsp, 1); - - if (vl_rbsp_more_data(rbsp)) { - pps->transform_8x8_mode_flag = vl_rbsp_u(rbsp, 1); - - /* pic_scaling_matrix_present_flag */ - if (vl_rbsp_u(rbsp, 1)) { - - scaling_list(rbsp, pps->ScalingList4x4[0], 16, Default_4x4_Intra, - sps->seq_scaling_matrix_present_flag ? NULL : Default_4x4_Intra); - scaling_list(rbsp, pps->ScalingList4x4[1], 16, Default_4x4_Intra, pps->ScalingList4x4[0]); - scaling_list(rbsp, pps->ScalingList4x4[2], 16, Default_4x4_Intra, pps->ScalingList4x4[1]); - scaling_list(rbsp, pps->ScalingList4x4[3], 16, Default_4x4_Inter, - sps->seq_scaling_matrix_present_flag ? NULL : Default_4x4_Inter); - scaling_list(rbsp, pps->ScalingList4x4[4], 16, Default_4x4_Inter, pps->ScalingList4x4[3]); - scaling_list(rbsp, pps->ScalingList4x4[5], 16, Default_4x4_Inter, pps->ScalingList4x4[4]); - - if (pps->transform_8x8_mode_flag) { - scaling_list(rbsp, pps->ScalingList8x8[0], 64, Default_8x8_Intra, - sps->seq_scaling_matrix_present_flag ? NULL : Default_8x8_Intra); - scaling_list(rbsp, pps->ScalingList8x8[1], 64, Default_8x8_Inter, - sps->seq_scaling_matrix_present_flag ? NULL : Default_8x8_Inter); - if (sps->chroma_format_idc == 3) { - scaling_list(rbsp, pps->ScalingList8x8[2], 64, Default_8x8_Intra, pps->ScalingList8x8[0]); - scaling_list(rbsp, pps->ScalingList8x8[3], 64, Default_8x8_Inter, pps->ScalingList8x8[1]); - scaling_list(rbsp, pps->ScalingList8x8[4], 64, Default_8x8_Intra, pps->ScalingList8x8[2]); - scaling_list(rbsp, pps->ScalingList8x8[5], 64, Default_8x8_Inter, pps->ScalingList8x8[3]); - } - } - } - - pps->second_chroma_qp_index_offset = vl_rbsp_se(rbsp); - } -} - -static void ref_pic_list_mvc_modification(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) -{ - // TODO - assert(0); -} - -static void ref_pic_list_modification(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, - enum pipe_h264_slice_type slice_type) -{ - unsigned modification_of_pic_nums_idc; - - if (slice_type != 2 && slice_type != 4) { - /* ref_pic_list_modification_flag_l0 */ - if (vl_rbsp_u(rbsp, 1)) { - do { - modification_of_pic_nums_idc = vl_rbsp_ue(rbsp); - if (modification_of_pic_nums_idc == 0 || - modification_of_pic_nums_idc == 1) - /* abs_diff_pic_num_minus1 */ - vl_rbsp_ue(rbsp); - else if (modification_of_pic_nums_idc == 2) - /* long_term_pic_num */ - vl_rbsp_ue(rbsp); - } while (modification_of_pic_nums_idc != 3); - } - } - - if (slice_type == 1) { - /* ref_pic_list_modification_flag_l1 */ - if (vl_rbsp_u(rbsp, 1)) { - do { - modification_of_pic_nums_idc = vl_rbsp_ue(rbsp); - if (modification_of_pic_nums_idc == 0 || - modification_of_pic_nums_idc == 1) - /* abs_diff_pic_num_minus1 */ - vl_rbsp_ue(rbsp); - else if (modification_of_pic_nums_idc == 2) - /* long_term_pic_num */ - vl_rbsp_ue(rbsp); - } while (modification_of_pic_nums_idc != 3); - } - } -} - -static void pred_weight_table(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, - struct pipe_h264_sps *sps, enum pipe_h264_slice_type slice_type) -{ - unsigned ChromaArrayType = sps->separate_colour_plane_flag ? 0 : sps->chroma_format_idc; - unsigned i, j; - - /* luma_log2_weight_denom */ - vl_rbsp_ue(rbsp); - - if (ChromaArrayType != 0) - /* chroma_log2_weight_denom */ - vl_rbsp_ue(rbsp); - - for (i = 0; i <= priv->picture.h264.num_ref_idx_l0_active_minus1; ++i) { - /* luma_weight_l0_flag */ - if (vl_rbsp_u(rbsp, 1)) { - /* luma_weight_l0[i] */ - vl_rbsp_se(rbsp); - /* luma_offset_l0[i] */ - vl_rbsp_se(rbsp); - } - if (ChromaArrayType != 0) { - /* chroma_weight_l0_flag */ - if (vl_rbsp_u(rbsp, 1)) { - for (j = 0; j < 2; ++j) { - /* chroma_weight_l0[i][j] */ - vl_rbsp_se(rbsp); - /* chroma_offset_l0[i][j] */ - vl_rbsp_se(rbsp); - } - } - } - } - - if (slice_type == 1) { - for (i = 0; i <= priv->picture.h264.num_ref_idx_l1_active_minus1; ++i) { - /* luma_weight_l1_flag */ - if (vl_rbsp_u(rbsp, 1)) { - /* luma_weight_l1[i] */ - vl_rbsp_se(rbsp); - /* luma_offset_l1[i] */ - vl_rbsp_se(rbsp); - } - if (ChromaArrayType != 0) { - /* chroma_weight_l1_flag */ - if (vl_rbsp_u(rbsp, 1)) { - for (j = 0; j < 2; ++j) { - /* chroma_weight_l1[i][j] */ - vl_rbsp_se(rbsp); - /* chroma_offset_l1[i][j] */ - vl_rbsp_se(rbsp); - } - } - } - } - } -} - -static void dec_ref_pic_marking(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, - bool IdrPicFlag) -{ - unsigned memory_management_control_operation; - - if (IdrPicFlag) { - /* no_output_of_prior_pics_flag */ - vl_rbsp_u(rbsp, 1); - /* long_term_reference_flag */ - vl_rbsp_u(rbsp, 1); - } else { - /* adaptive_ref_pic_marking_mode_flag */ - if (vl_rbsp_u(rbsp, 1)) { - do { - memory_management_control_operation = vl_rbsp_ue(rbsp); - - if (memory_management_control_operation == 1 || - memory_management_control_operation == 3) - /* difference_of_pic_nums_minus1 */ - vl_rbsp_ue(rbsp); - - if (memory_management_control_operation == 2) - /* long_term_pic_num */ - vl_rbsp_ue(rbsp); - - if (memory_management_control_operation == 3 || - memory_management_control_operation == 6) - /* long_term_frame_idx */ - vl_rbsp_ue(rbsp); - - if (memory_management_control_operation == 4) - /* max_long_term_frame_idx_plus1 */ - vl_rbsp_ue(rbsp); - } while (memory_management_control_operation != 0); - } - } -} - -static void slice_header(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, - unsigned nal_ref_idc, unsigned nal_unit_type) -{ - enum pipe_h264_slice_type slice_type; - struct pipe_h264_pps *pps; - struct pipe_h264_sps *sps; - unsigned frame_num, prevFrameNum; - bool IdrPicFlag = nal_unit_type == 5; - - if (IdrPicFlag != priv->codec_data.h264.IdrPicFlag) - vid_dec_h264_EndFrame(priv); - - priv->codec_data.h264.IdrPicFlag = IdrPicFlag; - - /* first_mb_in_slice */ - vl_rbsp_ue(rbsp); - - slice_type = vl_rbsp_ue(rbsp) % 5; - - pps = pic_parameter_set_id(priv, rbsp); - if (!pps) - return; - - sps = pps->sps; - if (!sps) - return; - - if (pps != priv->picture.h264.pps) - vid_dec_h264_EndFrame(priv); - - priv->picture.h264.pps = pps; - - if (sps->separate_colour_plane_flag == 1 ) - /* colour_plane_id */ - vl_rbsp_u(rbsp, 2); - - frame_num = vl_rbsp_u(rbsp, sps->log2_max_frame_num_minus4 + 4); - - if (frame_num != priv->picture.h264.frame_num) - vid_dec_h264_EndFrame(priv); - - prevFrameNum = priv->picture.h264.frame_num; - priv->picture.h264.frame_num = frame_num; - - priv->picture.h264.field_pic_flag = 0; - priv->picture.h264.bottom_field_flag = 0; - - if (!sps->frame_mbs_only_flag) { - unsigned field_pic_flag = vl_rbsp_u(rbsp, 1); - - if (!field_pic_flag && field_pic_flag != priv->picture.h264.field_pic_flag) - vid_dec_h264_EndFrame(priv); - - priv->picture.h264.field_pic_flag = field_pic_flag; - - if (priv->picture.h264.field_pic_flag) { - unsigned bottom_field_flag = vl_rbsp_u(rbsp, 1); - - if (bottom_field_flag != priv->picture.h264.bottom_field_flag) - vid_dec_h264_EndFrame(priv); - - priv->picture.h264.bottom_field_flag = bottom_field_flag; - } - } - - if (IdrPicFlag) { - unsigned idr_pic_id = vl_rbsp_ue(rbsp); - - if (idr_pic_id != priv->codec_data.h264.idr_pic_id) - vid_dec_h264_EndFrame(priv); - - priv->codec_data.h264.idr_pic_id = idr_pic_id; - } - - if (sps->pic_order_cnt_type == 0) { - unsigned log2_max_pic_order_cnt_lsb = sps->log2_max_pic_order_cnt_lsb_minus4 + 4; - unsigned max_pic_order_cnt_lsb = 1 << log2_max_pic_order_cnt_lsb; - int pic_order_cnt_lsb = vl_rbsp_u(rbsp, log2_max_pic_order_cnt_lsb); - int pic_order_cnt_msb; - - if (pic_order_cnt_lsb != priv->codec_data.h264.pic_order_cnt_lsb) - vid_dec_h264_EndFrame(priv); - - if (IdrPicFlag) { - priv->codec_data.h264.pic_order_cnt_msb = 0; - priv->codec_data.h264.pic_order_cnt_lsb = 0; - } - - if ((pic_order_cnt_lsb < priv->codec_data.h264.pic_order_cnt_lsb) && - (priv->codec_data.h264.pic_order_cnt_lsb - pic_order_cnt_lsb) >= (max_pic_order_cnt_lsb / 2)) - pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb + max_pic_order_cnt_lsb; - - else if ((pic_order_cnt_lsb > priv->codec_data.h264.pic_order_cnt_lsb) && - (pic_order_cnt_lsb - priv->codec_data.h264.pic_order_cnt_lsb) > (max_pic_order_cnt_lsb / 2)) - pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb - max_pic_order_cnt_lsb; - - else - pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb; - - priv->codec_data.h264.pic_order_cnt_msb = pic_order_cnt_msb; - priv->codec_data.h264.pic_order_cnt_lsb = pic_order_cnt_lsb; - - if (pps->bottom_field_pic_order_in_frame_present_flag && !priv->picture.h264.field_pic_flag) { - unsigned delta_pic_order_cnt_bottom = vl_rbsp_se(rbsp); - - if (delta_pic_order_cnt_bottom != priv->codec_data.h264.delta_pic_order_cnt_bottom) - vid_dec_h264_EndFrame(priv); - - priv->codec_data.h264.delta_pic_order_cnt_bottom = delta_pic_order_cnt_bottom; - } - - if (!priv->picture.h264.field_pic_flag) { - priv->picture.h264.field_order_cnt[0] = pic_order_cnt_msb + pic_order_cnt_lsb; - priv->picture.h264.field_order_cnt[1] = priv->picture.h264.field_order_cnt [0] + - priv->codec_data.h264.delta_pic_order_cnt_bottom; - } else if (!priv->picture.h264.bottom_field_flag) - priv->picture.h264.field_order_cnt[0] = pic_order_cnt_msb + pic_order_cnt_lsb; - else - priv->picture.h264.field_order_cnt[1] = pic_order_cnt_msb + pic_order_cnt_lsb; - - } else if (sps->pic_order_cnt_type == 1) { - unsigned MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4); - unsigned FrameNumOffset, absFrameNum, expectedPicOrderCnt; - - if (!sps->delta_pic_order_always_zero_flag) { - unsigned delta_pic_order_cnt[2]; - - delta_pic_order_cnt[0] = vl_rbsp_se(rbsp); - - if (delta_pic_order_cnt[0] != priv->codec_data.h264.delta_pic_order_cnt[0]) - vid_dec_h264_EndFrame(priv); - - priv->codec_data.h264.delta_pic_order_cnt[0] = delta_pic_order_cnt[0]; - - if (pps->bottom_field_pic_order_in_frame_present_flag && !priv->picture.h264.field_pic_flag) { - delta_pic_order_cnt[1] = vl_rbsp_se(rbsp); - - if (delta_pic_order_cnt[1] != priv->codec_data.h264.delta_pic_order_cnt[1]) - vid_dec_h264_EndFrame(priv); - - priv->codec_data.h264.delta_pic_order_cnt[1] = delta_pic_order_cnt[1]; - } - } - - if (IdrPicFlag) - FrameNumOffset = 0; - else if (prevFrameNum > frame_num) - FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset + MaxFrameNum; - else - FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset; - - priv->codec_data.h264.prevFrameNumOffset = FrameNumOffset; - - if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0) - absFrameNum = FrameNumOffset + frame_num; - else - absFrameNum = 0; - - if (nal_ref_idc == 0 && absFrameNum > 0) - absFrameNum = absFrameNum - 1; - - if (absFrameNum > 0) { - unsigned picOrderCntCycleCnt = (absFrameNum - 1) / sps->num_ref_frames_in_pic_order_cnt_cycle; - unsigned frameNumInPicOrderCntCycle = (absFrameNum - 1) % sps->num_ref_frames_in_pic_order_cnt_cycle; - signed ExpectedDeltaPerPicOrderCntCycle = 0; - unsigned i; - - for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) - ExpectedDeltaPerPicOrderCntCycle += sps->offset_for_ref_frame[i]; - - expectedPicOrderCnt = picOrderCntCycleCnt * ExpectedDeltaPerPicOrderCntCycle; - for (i = 0; i <= frameNumInPicOrderCntCycle; ++i) - expectedPicOrderCnt += sps->offset_for_ref_frame[i]; - - } else - expectedPicOrderCnt = 0; - - if (nal_ref_idc == 0) - expectedPicOrderCnt += sps->offset_for_non_ref_pic; - - if (!priv->picture.h264.field_pic_flag) { - priv->picture.h264.field_order_cnt[0] = expectedPicOrderCnt + priv->codec_data.h264.delta_pic_order_cnt[0]; - priv->picture.h264.field_order_cnt[1] = priv->picture.h264.field_order_cnt[0] + - sps->offset_for_top_to_bottom_field + priv->codec_data.h264.delta_pic_order_cnt[1]; - - } else if (!priv->picture.h264.bottom_field_flag) - priv->picture.h264.field_order_cnt[0] = expectedPicOrderCnt + priv->codec_data.h264.delta_pic_order_cnt[0]; - else - priv->picture.h264.field_order_cnt[1] = expectedPicOrderCnt + sps->offset_for_top_to_bottom_field + - priv->codec_data.h264.delta_pic_order_cnt[0]; - - } else if (sps->pic_order_cnt_type == 2) { - unsigned MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4); - unsigned FrameNumOffset, tempPicOrderCnt; - - if (IdrPicFlag) - FrameNumOffset = 0; - else if (prevFrameNum > frame_num) - FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset + MaxFrameNum; - else - FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset; - - priv->codec_data.h264.prevFrameNumOffset = FrameNumOffset; - - if (IdrPicFlag) - tempPicOrderCnt = 0; - else if (nal_ref_idc == 0) - tempPicOrderCnt = 2 * (FrameNumOffset + frame_num) - 1; - else - tempPicOrderCnt = 2 * (FrameNumOffset + frame_num); - - if (!priv->picture.h264.field_pic_flag) { - priv->picture.h264.field_order_cnt[0] = tempPicOrderCnt; - priv->picture.h264.field_order_cnt[1] = tempPicOrderCnt; - - } else if (!priv->picture.h264.bottom_field_flag) - priv->picture.h264.field_order_cnt[0] = tempPicOrderCnt; - else - priv->picture.h264.field_order_cnt[1] = tempPicOrderCnt; - } - - if (pps->redundant_pic_cnt_present_flag) - /* redundant_pic_cnt */ - vl_rbsp_ue(rbsp); - - if (slice_type == PIPE_H264_SLICE_TYPE_B) - /* direct_spatial_mv_pred_flag */ - vl_rbsp_u(rbsp, 1); - - priv->picture.h264.num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_default_active_minus1; - priv->picture.h264.num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_default_active_minus1; - - if (slice_type == PIPE_H264_SLICE_TYPE_P || - slice_type == PIPE_H264_SLICE_TYPE_SP || - slice_type == PIPE_H264_SLICE_TYPE_B) { - - /* num_ref_idx_active_override_flag */ - if (vl_rbsp_u(rbsp, 1)) { - priv->picture.h264.num_ref_idx_l0_active_minus1 = vl_rbsp_ue(rbsp); - - if (slice_type == PIPE_H264_SLICE_TYPE_B) - priv->picture.h264.num_ref_idx_l1_active_minus1 = vl_rbsp_ue(rbsp); - } - } - - if (nal_unit_type == 20 || nal_unit_type == 21) - ref_pic_list_mvc_modification(priv, rbsp); - else - ref_pic_list_modification(priv, rbsp, slice_type); - - if ((pps->weighted_pred_flag && (slice_type == PIPE_H264_SLICE_TYPE_P || slice_type == PIPE_H264_SLICE_TYPE_SP)) || - (pps->weighted_bipred_idc == 1 && slice_type == PIPE_H264_SLICE_TYPE_B)) - pred_weight_table(priv, rbsp, sps, slice_type); - - if (nal_ref_idc != 0) - dec_ref_pic_marking(priv, rbsp, IdrPicFlag); - - if (pps->entropy_coding_mode_flag && slice_type != PIPE_H264_SLICE_TYPE_I && slice_type != PIPE_H264_SLICE_TYPE_SI) - /* cabac_init_idc */ - vl_rbsp_ue(rbsp); - - /* slice_qp_delta */ - vl_rbsp_se(rbsp); - - if (slice_type == PIPE_H264_SLICE_TYPE_SP || slice_type == PIPE_H264_SLICE_TYPE_SI) { - if (slice_type == PIPE_H264_SLICE_TYPE_SP) - /* sp_for_switch_flag */ - vl_rbsp_u(rbsp, 1); - - /*slice_qs_delta */ - vl_rbsp_se(rbsp); - } - - if (pps->deblocking_filter_control_present_flag) { - unsigned disable_deblocking_filter_idc = vl_rbsp_ue(rbsp); - - if (disable_deblocking_filter_idc != 1) { - /* slice_alpha_c0_offset_div2 */ - vl_rbsp_se(rbsp); - - /* slice_beta_offset_div2 */ - vl_rbsp_se(rbsp); - } - } - - if (pps->num_slice_groups_minus1 > 0 && pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5) - /* slice_group_change_cycle */ - vl_rbsp_u(rbsp, 2); -} - -static void vid_dec_h264_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left) -{ - unsigned nal_ref_idc, nal_unit_type; - - if (!vl_vlc_search_byte(vlc, vl_vlc_bits_left(vlc) - min_bits_left, 0x00)) - return; - - if (vl_vlc_peekbits(vlc, 24) != 0x000001) { - vl_vlc_eatbits(vlc, 8); - return; - } - - if (priv->slice) { - unsigned bytes = priv->bytes_left - (vl_vlc_bits_left(vlc) / 8); - ++priv->picture.h264.slice_count; - priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, - 1, &priv->slice, &bytes); - priv->slice = NULL; - } - - vl_vlc_eatbits(vlc, 24); - - /* forbidden_zero_bit */ - vl_vlc_eatbits(vlc, 1); - - nal_ref_idc = vl_vlc_get_uimsbf(vlc, 2); - - if (nal_ref_idc != priv->codec_data.h264.nal_ref_idc && - (nal_ref_idc * priv->codec_data.h264.nal_ref_idc) == 0) - vid_dec_h264_EndFrame(priv); - - priv->codec_data.h264.nal_ref_idc = nal_ref_idc; - - nal_unit_type = vl_vlc_get_uimsbf(vlc, 5); - - if (nal_unit_type != 1 && nal_unit_type != 5) - vid_dec_h264_EndFrame(priv); - - if (nal_unit_type == 7) { - struct vl_rbsp rbsp; - vl_rbsp_init(&rbsp, vlc, ~0); - seq_parameter_set(priv, &rbsp); - - } else if (nal_unit_type == 8) { - struct vl_rbsp rbsp; - vl_rbsp_init(&rbsp, vlc, ~0); - picture_parameter_set(priv, &rbsp); - - } else if (nal_unit_type == 1 || nal_unit_type == 5) { - /* Coded slice of a non-IDR or IDR picture */ - unsigned bits = vl_vlc_valid_bits(vlc); - unsigned bytes = bits / 8 + 4; - struct vl_rbsp rbsp; - uint8_t buf[8]; - const void *ptr = buf; - unsigned i; - - buf[0] = 0x0; - buf[1] = 0x0; - buf[2] = 0x1; - buf[3] = (nal_ref_idc << 5) | nal_unit_type; - for (i = 4; i < bytes; ++i) - buf[i] = vl_vlc_peekbits(vlc, bits) >> ((bytes - i - 1) * 8); - - priv->bytes_left = (vl_vlc_bits_left(vlc) - bits) / 8; - priv->slice = vlc->data; - - vl_rbsp_init(&rbsp, vlc, 128); - slice_header(priv, &rbsp, nal_ref_idc, nal_unit_type); - - vid_dec_h264_BeginFrame(priv); - - ++priv->picture.h264.slice_count; - priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, - 1, &ptr, &bytes); - } - - /* resync to byte boundary */ - vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8); -} diff --git a/src/gallium/state_trackers/omx/vid_dec_h265.c b/src/gallium/state_trackers/omx/vid_dec_h265.c deleted file mode 100644 index 3242dbe11c8..00000000000 --- a/src/gallium/state_trackers/omx/vid_dec_h265.c +++ /dev/null @@ -1,1013 +0,0 @@ -/************************************************************************** - * - * Copyright 2016 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "pipe/p_video_codec.h" -#include "util/u_memory.h" -#include "util/u_video.h" -#include "vl/vl_rbsp.h" - -#include "entrypoint.h" -#include "vid_dec.h" - -#define DPB_MAX_SIZE 32 -#define MAX_NUM_REF_PICS 16 - -enum { - NAL_UNIT_TYPE_TRAIL_N = 0, - NAL_UNIT_TYPE_TRAIL_R = 1, - NAL_UNIT_TYPE_TSA_N = 2, - NAL_UNIT_TYPE_TSA_R = 3, - NAL_UNIT_TYPE_STSA_N = 4, - NAL_UNIT_TYPE_STSA_R = 5, - NAL_UNIT_TYPE_RADL_N = 6, - NAL_UNIT_TYPE_RADL_R = 7, - NAL_UNIT_TYPE_RASL_N = 8, - NAL_UNIT_TYPE_RASL_R = 9, - NAL_UNIT_TYPE_BLA_W_LP = 16, - NAL_UNIT_TYPE_BLA_W_RADL = 17, - NAL_UNIT_TYPE_BLA_N_LP = 18, - NAL_UNIT_TYPE_IDR_W_RADL = 19, - NAL_UNIT_TYPE_IDR_N_LP = 20, - NAL_UNIT_TYPE_CRA = 21, - NAL_UNIT_TYPE_SPS = 33, - NAL_UNIT_TYPE_PPS = 34, -}; - -static const uint8_t Default_8x8_Intra[64] = { - 16, 16, 16, 16, 17, 18, 21, 24, - 16, 16, 16, 16, 17, 19, 22, 25, - 16, 16, 17, 18, 20, 22, 25, 29, - 16, 16, 18, 21, 24, 27, 31, 36, - 17, 17, 20, 24, 30, 35, 41, 47, - 18, 19, 22, 27, 35, 44, 54, 65, - 21, 22, 25, 31, 41, 54, 70, 88, - 24, 25, 29, 36, 47, 65, 88, 115 -}; - -static const uint8_t Default_8x8_Inter[64] = { - 16, 16, 16, 16, 17, 18, 20, 24, - 16, 16, 16, 17, 18, 20, 24, 25, - 16, 16, 17, 18, 20, 24, 25, 28, - 16, 17, 18, 20, 24, 25, 28, 33, - 17, 18, 20, 24, 25, 28, 33, 41, - 18, 20, 24, 25, 28, 33, 41, 54, - 20, 24, 25, 28, 33, 41, 54, 71, - 24, 25, 28, 33, 41, 54, 71, 91 -}; - -struct dpb_list { - struct list_head list; - struct pipe_video_buffer *buffer; - OMX_TICKS timestamp; - unsigned poc; -}; - -struct ref_pic_set { - unsigned num_pics; - unsigned num_neg_pics; - unsigned num_pos_pics; - unsigned num_delta_poc; - int delta_poc[MAX_NUM_REF_PICS]; - bool used[MAX_NUM_REF_PICS]; -}; - -static bool is_idr_picture(unsigned nal_unit_type) -{ - return (nal_unit_type == NAL_UNIT_TYPE_IDR_W_RADL || - nal_unit_type == NAL_UNIT_TYPE_IDR_N_LP); -} - -/* broken link access picture */ -static bool is_bla_picture(unsigned nal_unit_type) -{ - return (nal_unit_type == NAL_UNIT_TYPE_BLA_W_LP || - nal_unit_type == NAL_UNIT_TYPE_BLA_W_RADL || - nal_unit_type == NAL_UNIT_TYPE_BLA_N_LP); -} - -/* random access point picture */ -static bool is_rap_picture(unsigned nal_unit_type) -{ - return (nal_unit_type >= NAL_UNIT_TYPE_BLA_W_LP && - nal_unit_type <= NAL_UNIT_TYPE_CRA); -} - -static bool is_slice_picture(unsigned nal_unit_type) -{ - return (nal_unit_type <= NAL_UNIT_TYPE_RASL_R || - is_rap_picture(nal_unit_type)); -} - -static void set_poc(vid_dec_PrivateType *priv, - unsigned nal_unit_type, int i) -{ - priv->picture.h265.CurrPicOrderCntVal = i; - - if (priv->codec_data.h265.temporal_id == 0 && - (nal_unit_type == NAL_UNIT_TYPE_TRAIL_R || - nal_unit_type == NAL_UNIT_TYPE_TSA_R || - nal_unit_type == NAL_UNIT_TYPE_STSA_R || - is_rap_picture(nal_unit_type))) - priv->codec_data.h265.slice_prev_poc = i; -} - -static unsigned get_poc(vid_dec_PrivateType *priv) -{ - return priv->picture.h265.CurrPicOrderCntVal; -} - -static void profile_tier(struct vl_rbsp *rbsp) -{ - int i; - - /* general_profile_space */ - vl_rbsp_u(rbsp, 2); - - /* general_tier_flag */ - vl_rbsp_u(rbsp, 1); - - /* general_profile_idc */ - vl_rbsp_u(rbsp, 5); - - /* general_profile_compatibility_flag */ - for(i = 0; i < 32; ++i) - vl_rbsp_u(rbsp, 1); - - /* general_progressive_source_flag */ - vl_rbsp_u(rbsp, 1); - - /* general_interlaced_source_flag */ - vl_rbsp_u(rbsp, 1); - - /* general_non_packed_constraint_flag */ - vl_rbsp_u(rbsp, 1); - - /* general_frame_only_constraint_flag */ - vl_rbsp_u(rbsp, 1); - - /* general_reserved_zero_44bits */ - vl_rbsp_u(rbsp, 16); - vl_rbsp_u(rbsp, 16); - vl_rbsp_u(rbsp, 12); -} - -static unsigned profile_tier_level(struct vl_rbsp *rbsp, - int max_sublayers_minus1) -{ - bool sub_layer_profile_present_flag[6]; - bool sub_layer_level_present_flag[6]; - unsigned level_idc; - int i; - - profile_tier(rbsp); - - /* general_level_idc */ - level_idc = vl_rbsp_u(rbsp, 8); - - for (i = 0; i < max_sublayers_minus1; ++i) { - sub_layer_profile_present_flag[i] = vl_rbsp_u(rbsp, 1); - sub_layer_level_present_flag[i] = vl_rbsp_u(rbsp, 1); - } - - if (max_sublayers_minus1 > 0) - for (i = max_sublayers_minus1; i < 8; ++i) - /* reserved_zero_2bits */ - vl_rbsp_u(rbsp, 2); - - for (i = 0; i < max_sublayers_minus1; ++i) { - if (sub_layer_profile_present_flag[i]) - profile_tier(rbsp); - - if (sub_layer_level_present_flag[i]) - /* sub_layer_level_idc */ - vl_rbsp_u(rbsp, 8); - } - - return level_idc; -} - -static void scaling_list_data(vid_dec_PrivateType *priv, - struct vl_rbsp *rbsp, struct pipe_h265_sps *sps) -{ - unsigned size_id, matrix_id; - unsigned scaling_list_len[4] = { 16, 64, 64, 64 }; - uint8_t scaling_list4x4[6][64] = { }; - int i; - - uint8_t (*scaling_list_data[4])[6][64] = { - (uint8_t (*)[6][64])scaling_list4x4, - (uint8_t (*)[6][64])sps->ScalingList8x8, - (uint8_t (*)[6][64])sps->ScalingList16x16, - (uint8_t (*)[6][64])sps->ScalingList32x32 - }; - uint8_t (*scaling_list_dc_coeff[2])[6] = { - (uint8_t (*)[6])sps->ScalingListDCCoeff16x16, - (uint8_t (*)[6])sps->ScalingListDCCoeff32x32 - }; - - for (size_id = 0; size_id < 4; ++size_id) { - - for (matrix_id = 0; matrix_id < ((size_id == 3) ? 2 : 6); ++matrix_id) { - bool scaling_list_pred_mode_flag = vl_rbsp_u(rbsp, 1); - - if (!scaling_list_pred_mode_flag) { - /* scaling_list_pred_matrix_id_delta */; - unsigned matrix_id_with_delta = matrix_id - vl_rbsp_ue(rbsp); - - if (matrix_id != matrix_id_with_delta) { - memcpy((*scaling_list_data[size_id])[matrix_id], - (*scaling_list_data[size_id])[matrix_id_with_delta], - scaling_list_len[size_id]); - if (size_id > 1) - (*scaling_list_dc_coeff[size_id - 2])[matrix_id] = - (*scaling_list_dc_coeff[size_id - 2])[matrix_id_with_delta]; - } else { - const uint8_t *d; - - if (size_id == 0) - memset((*scaling_list_data[0])[matrix_id], 16, 16); - else { - if (size_id < 3) - d = (matrix_id < 3) ? Default_8x8_Intra : Default_8x8_Inter; - else - d = (matrix_id < 1) ? Default_8x8_Intra : Default_8x8_Inter; - memcpy((*scaling_list_data[size_id])[matrix_id], d, - scaling_list_len[size_id]); - } - if (size_id > 1) - (*scaling_list_dc_coeff[size_id - 2])[matrix_id] = 16; - } - } else { - int next_coef = 8; - int coef_num = MIN2(64, (1 << (4 + (size_id << 1)))); - - if (size_id > 1) { - /* scaling_list_dc_coef_minus8 */ - next_coef = vl_rbsp_se(rbsp) + 8; - (*scaling_list_dc_coeff[size_id - 2])[matrix_id] = next_coef; - } - - for (i = 0; i < coef_num; ++i) { - /* scaling_list_delta_coef */ - next_coef = (next_coef + vl_rbsp_se(rbsp) + 256) % 256; - (*scaling_list_data[size_id])[matrix_id][i] = next_coef; - } - } - } - } - - for (i = 0; i < 6; ++i) - memcpy(sps->ScalingList4x4[i], scaling_list4x4[i], 16); - - return; -} - -static void st_ref_pic_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, - struct ref_pic_set *rps, struct pipe_h265_sps *sps, - unsigned idx) -{ - bool inter_rps_pred_flag; - unsigned delta_idx_minus1; - int delta_poc; - int i; - - inter_rps_pred_flag = (idx != 0) ? (vl_rbsp_u(rbsp, 1)) : false; - - if (inter_rps_pred_flag) { - struct ref_pic_set *ref_rps; - unsigned sign, abs; - int delta_rps; - bool used; - int j; - - if (idx == sps->num_short_term_ref_pic_sets) - delta_idx_minus1 = vl_rbsp_ue(rbsp); - else - delta_idx_minus1 = 0; - - ref_rps = (struct ref_pic_set *) - priv->codec_data.h265.ref_pic_set_list + idx - (delta_idx_minus1 + 1); - - /* delta_rps_sign */ - sign = vl_rbsp_u(rbsp, 1); - /* abs_delta_rps_minus1 */ - abs = vl_rbsp_ue(rbsp); - delta_rps = (1 - 2 * sign) * (abs + 1); - - rps->num_neg_pics = 0; - rps->num_pos_pics = 0; - rps->num_pics = 0; - - for(i = 0 ; i <= ref_rps->num_pics; ++i) { - /* used_by_curr_pic_flag */ - if (!vl_rbsp_u(rbsp, 1)) - /* use_delta_flag */ - vl_rbsp_u(rbsp, 1); - else { - delta_poc = delta_rps + - ((i < ref_rps->num_pics)? ref_rps->delta_poc[i] : 0); - rps->delta_poc[rps->num_pics] = delta_poc; - rps->used[rps->num_pics] = true; - if (delta_poc < 0) - rps->num_neg_pics++; - else - rps->num_pos_pics++; - rps->num_pics++; - } - } - - rps->num_delta_poc = ref_rps->num_pics; - - /* sort delta poc */ - for (i = 1; i < rps->num_pics; ++i) { - delta_poc = rps->delta_poc[i]; - used = rps->used[i]; - for (j = i - 1; j >= 0; j--) { - if (delta_poc < rps->delta_poc[j]) { - rps->delta_poc[j + 1] = rps->delta_poc[j]; - rps->used[j + 1] = rps->used[j]; - rps->delta_poc[j] = delta_poc; - rps->used[j] = used; - } - } - } - - for (i = 0 , j = rps->num_neg_pics - 1; - i < rps->num_neg_pics >> 1; i++, j--) { - delta_poc = rps->delta_poc[i]; - used = rps->used[i]; - rps->delta_poc[i] = rps->delta_poc[j]; - rps->used[i] = rps->used[j]; - rps->delta_poc[j] = delta_poc; - rps->used[j] = used; - } - } else { - /* num_negative_pics */ - rps->num_neg_pics = vl_rbsp_ue(rbsp); - /* num_positive_pics */ - rps->num_pos_pics = vl_rbsp_ue(rbsp); - rps->num_pics = rps->num_neg_pics + rps->num_pos_pics; - - delta_poc = 0; - for(i = 0 ; i < rps->num_neg_pics; ++i) { - /* delta_poc_s0_minus1 */ - delta_poc -= (vl_rbsp_ue(rbsp) + 1); - rps->delta_poc[i] = delta_poc; - /* used_by_curr_pic_s0_flag */ - rps->used[i] = vl_rbsp_u(rbsp, 1); - } - - delta_poc = 0; - for(i = rps->num_neg_pics; i < rps->num_pics; ++i) { - /* delta_poc_s1_minus1 */ - delta_poc += (vl_rbsp_ue(rbsp) + 1); - rps->delta_poc[i] = delta_poc; - /* used_by_curr_pic_s1_flag */ - rps->used[i] = vl_rbsp_u(rbsp, 1); - } - } -} - -static struct pipe_h265_sps *seq_parameter_set_id(vid_dec_PrivateType *priv, - struct vl_rbsp *rbsp) -{ - unsigned id = vl_rbsp_ue(rbsp); - - if (id >= ARRAY_SIZE(priv->codec_data.h265.sps)) - return NULL; - - return &priv->codec_data.h265.sps[id]; -} - -static void seq_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) -{ - struct pipe_h265_sps *sps; - int sps_max_sub_layers_minus1; - unsigned i; - - /* sps_video_parameter_set_id */ - vl_rbsp_u(rbsp, 4); - - /* sps_max_sub_layers_minus1 */ - sps_max_sub_layers_minus1 = vl_rbsp_u(rbsp, 3); - - assert(sps_max_sub_layers_minus1 <= 6); - - /* sps_temporal_id_nesting_flag */ - vl_rbsp_u(rbsp, 1); - - priv->codec_data.h265.level_idc = - profile_tier_level(rbsp, sps_max_sub_layers_minus1); - - sps = seq_parameter_set_id(priv, rbsp); - if (!sps) - return; - - memset(sps, 0, sizeof(*sps)); - - sps->chroma_format_idc = vl_rbsp_ue(rbsp); - - if (sps->chroma_format_idc == 3) - sps->separate_colour_plane_flag = vl_rbsp_u(rbsp, 1); - - priv->codec_data.h265.pic_width_in_luma_samples = - sps->pic_width_in_luma_samples = vl_rbsp_ue(rbsp); - - priv->codec_data.h265.pic_height_in_luma_samples = - sps->pic_height_in_luma_samples = vl_rbsp_ue(rbsp); - - /* conformance_window_flag */ - if (vl_rbsp_u(rbsp, 1)) { - /* conf_win_left_offset */ - vl_rbsp_ue(rbsp); - /* conf_win_right_offset */ - vl_rbsp_ue(rbsp); - /* conf_win_top_offset */ - vl_rbsp_ue(rbsp); - /* conf_win_bottom_offset */ - vl_rbsp_ue(rbsp); - } - - sps->bit_depth_luma_minus8 = vl_rbsp_ue(rbsp); - sps->bit_depth_chroma_minus8 = vl_rbsp_ue(rbsp); - sps->log2_max_pic_order_cnt_lsb_minus4 = vl_rbsp_ue(rbsp); - - /* sps_sub_layer_ordering_info_present_flag */ - i = vl_rbsp_u(rbsp, 1) ? 0 : sps_max_sub_layers_minus1; - for (; i <= sps_max_sub_layers_minus1; ++i) { - sps->sps_max_dec_pic_buffering_minus1 = vl_rbsp_ue(rbsp); - /* sps_max_num_reorder_pics */ - vl_rbsp_ue(rbsp); - /* sps_max_latency_increase_plus */ - vl_rbsp_ue(rbsp); - } - - sps->log2_min_luma_coding_block_size_minus3 = vl_rbsp_ue(rbsp); - sps->log2_diff_max_min_luma_coding_block_size = vl_rbsp_ue(rbsp); - sps->log2_min_transform_block_size_minus2 = vl_rbsp_ue(rbsp); - sps->log2_diff_max_min_transform_block_size = vl_rbsp_ue(rbsp); - sps->max_transform_hierarchy_depth_inter = vl_rbsp_ue(rbsp); - sps->max_transform_hierarchy_depth_intra = vl_rbsp_ue(rbsp); - - sps->scaling_list_enabled_flag = vl_rbsp_u(rbsp, 1); - if (sps->scaling_list_enabled_flag) - /* sps_scaling_list_data_present_flag */ - if (vl_rbsp_u(rbsp, 1)) - scaling_list_data(priv, rbsp, sps); - - sps->amp_enabled_flag = vl_rbsp_u(rbsp, 1); - sps->sample_adaptive_offset_enabled_flag = vl_rbsp_u(rbsp, 1); - sps->pcm_enabled_flag = vl_rbsp_u(rbsp, 1); - if (sps->pcm_enabled_flag) { - sps->pcm_sample_bit_depth_luma_minus1 = vl_rbsp_u(rbsp, 4); - sps->pcm_sample_bit_depth_chroma_minus1 = vl_rbsp_u(rbsp, 4); - sps->log2_min_pcm_luma_coding_block_size_minus3 = vl_rbsp_ue(rbsp); - sps->log2_diff_max_min_pcm_luma_coding_block_size = vl_rbsp_ue(rbsp); - sps->pcm_loop_filter_disabled_flag = vl_rbsp_u(rbsp, 1); - } - - sps->num_short_term_ref_pic_sets = vl_rbsp_ue(rbsp); - - for (i = 0; i < sps->num_short_term_ref_pic_sets; ++i) { - struct ref_pic_set *rps; - - rps = (struct ref_pic_set *) - priv->codec_data.h265.ref_pic_set_list + i; - st_ref_pic_set(priv, rbsp, rps, sps, i); - } - - sps->long_term_ref_pics_present_flag = vl_rbsp_u(rbsp, 1); - if (sps->long_term_ref_pics_present_flag) { - sps->num_long_term_ref_pics_sps = vl_rbsp_ue(rbsp); - for (i = 0; i < sps->num_long_term_ref_pics_sps; ++i) { - /* lt_ref_pic_poc_lsb_sps */ - vl_rbsp_u(rbsp, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); - /* used_by_curr_pic_lt_sps_flag */ - vl_rbsp_u(rbsp, 1); - } - } - - sps->sps_temporal_mvp_enabled_flag = vl_rbsp_u(rbsp, 1); - sps->strong_intra_smoothing_enabled_flag = vl_rbsp_u(rbsp, 1); -} - -static struct pipe_h265_pps *pic_parameter_set_id(vid_dec_PrivateType *priv, - struct vl_rbsp *rbsp) -{ - unsigned id = vl_rbsp_ue(rbsp); - - if (id >= ARRAY_SIZE(priv->codec_data.h265.pps)) - return NULL; - - return &priv->codec_data.h265.pps[id]; -} - -static void picture_parameter_set(vid_dec_PrivateType *priv, - struct vl_rbsp *rbsp) -{ - struct pipe_h265_sps *sps; - struct pipe_h265_pps *pps; - int i; - - pps = pic_parameter_set_id(priv, rbsp); - if (!pps) - return; - - memset(pps, 0, sizeof(*pps)); - sps = pps->sps = seq_parameter_set_id(priv, rbsp); - if (!sps) - return; - - pps->dependent_slice_segments_enabled_flag = vl_rbsp_u(rbsp, 1); - pps->output_flag_present_flag = vl_rbsp_u(rbsp, 1); - pps->num_extra_slice_header_bits = vl_rbsp_u(rbsp, 3); - pps->sign_data_hiding_enabled_flag = vl_rbsp_u(rbsp, 1); - pps->cabac_init_present_flag = vl_rbsp_u(rbsp, 1); - - pps->num_ref_idx_l0_default_active_minus1 = vl_rbsp_ue(rbsp); - pps->num_ref_idx_l1_default_active_minus1 = vl_rbsp_ue(rbsp); - pps->init_qp_minus26 = vl_rbsp_se(rbsp); - pps->constrained_intra_pred_flag = vl_rbsp_u(rbsp, 1); - pps->transform_skip_enabled_flag = vl_rbsp_u(rbsp, 1); - - pps->cu_qp_delta_enabled_flag = vl_rbsp_u(rbsp, 1); - if (pps->cu_qp_delta_enabled_flag) - pps->diff_cu_qp_delta_depth = vl_rbsp_ue(rbsp); - - pps->pps_cb_qp_offset = vl_rbsp_se(rbsp); - pps->pps_cr_qp_offset = vl_rbsp_se(rbsp); - pps->pps_slice_chroma_qp_offsets_present_flag = vl_rbsp_u(rbsp, 1); - - pps->weighted_pred_flag = vl_rbsp_u(rbsp, 1); - pps->weighted_bipred_flag = vl_rbsp_u(rbsp, 1); - - pps->transquant_bypass_enabled_flag = vl_rbsp_u(rbsp, 1); - pps->tiles_enabled_flag = vl_rbsp_u(rbsp, 1); - pps->entropy_coding_sync_enabled_flag = vl_rbsp_u(rbsp, 1); - - if (pps->tiles_enabled_flag) { - pps->num_tile_columns_minus1 = vl_rbsp_ue(rbsp); - pps->num_tile_rows_minus1 = vl_rbsp_ue(rbsp); - - pps->uniform_spacing_flag = vl_rbsp_u(rbsp, 1); - if (!pps->uniform_spacing_flag) { - for (i = 0; i < pps->num_tile_columns_minus1; ++i) - pps->column_width_minus1[i] = vl_rbsp_ue(rbsp); - - for (i = 0; i < pps->num_tile_rows_minus1; ++i) - pps->row_height_minus1[i] = vl_rbsp_ue(rbsp); - } - - if (!pps->num_tile_columns_minus1 || !pps->num_tile_rows_minus1) - pps->loop_filter_across_tiles_enabled_flag = vl_rbsp_u(rbsp, 1); - } - - pps->pps_loop_filter_across_slices_enabled_flag = vl_rbsp_u(rbsp, 1); - - pps->deblocking_filter_control_present_flag = vl_rbsp_u(rbsp, 1); - if (pps->deblocking_filter_control_present_flag) { - pps->deblocking_filter_override_enabled_flag = vl_rbsp_u(rbsp, 1); - pps->pps_deblocking_filter_disabled_flag = vl_rbsp_u(rbsp, 1); - if (!pps->pps_deblocking_filter_disabled_flag) { - pps->pps_beta_offset_div2 = vl_rbsp_se(rbsp); - pps->pps_tc_offset_div2 = vl_rbsp_se(rbsp); - } - } - - /* pps_scaling_list_data_present_flag */ - if (vl_rbsp_u(rbsp, 1)) - scaling_list_data(priv, rbsp, sps); - - pps->lists_modification_present_flag = vl_rbsp_u(rbsp, 1); - pps->log2_parallel_merge_level_minus2 = vl_rbsp_ue(rbsp); - pps->slice_segment_header_extension_present_flag = vl_rbsp_u(rbsp, 1); -} - -static void vid_dec_h265_BeginFrame(vid_dec_PrivateType *priv) -{ - if (priv->frame_started) - return; - - if (!priv->codec) { - struct pipe_video_codec templat = {}; - omx_base_video_PortType *port = (omx_base_video_PortType *) - priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; - - templat.profile = priv->profile; - templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; - templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - templat.expect_chunked_decode = true; - templat.width = priv->codec_data.h265.pic_width_in_luma_samples; - templat.height = priv->codec_data.h265.pic_height_in_luma_samples; - templat.level = priv->codec_data.h265.level_idc; - priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat); - - /* disable transcode tunnel if video size is different from coded size */ - if (priv->codec_data.h265.pic_width_in_luma_samples != - port->sPortParam.format.video.nFrameWidth || - priv->codec_data.h265.pic_height_in_luma_samples != - port->sPortParam.format.video.nFrameHeight) - priv->disable_tunnel = true; - } - - vid_dec_NeedTarget(priv); - - if (priv->first_buf_in_frame) - priv->timestamp = priv->timestamps[0]; - priv->first_buf_in_frame = false; - - priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base); - priv->frame_started = true; -} - -static struct pipe_video_buffer *vid_dec_h265_Flush(vid_dec_PrivateType *priv, - OMX_TICKS *timestamp) -{ - struct dpb_list *entry, *result = NULL; - struct pipe_video_buffer *buf; - - /* search for the lowest poc and break on zeros */ - LIST_FOR_EACH_ENTRY(entry, &priv->codec_data.h265.dpb_list, list) { - - if (result && entry->poc == 0) - break; - - if (!result || entry->poc < result->poc) - result = entry; - } - - if (!result) - return NULL; - - buf = result->buffer; - if (timestamp) - *timestamp = result->timestamp; - - --priv->codec_data.h265.dpb_num; - LIST_DEL(&result->list); - FREE(result); - - return buf; -} - -static void vid_dec_h265_EndFrame(vid_dec_PrivateType *priv) -{ - struct dpb_list *entry = NULL; - struct pipe_video_buffer *tmp; - struct ref_pic_set *rps; - int i; - OMX_TICKS timestamp; - - if (!priv->frame_started) - return; - - priv->picture.h265.NumPocStCurrBefore = 0; - priv->picture.h265.NumPocStCurrAfter = 0; - memset(priv->picture.h265.RefPicSetStCurrBefore, 0, 8); - memset(priv->picture.h265.RefPicSetStCurrAfter, 0, 8); - for (i = 0; i < MAX_NUM_REF_PICS; ++i) { - priv->picture.h265.ref[i] = NULL; - priv->picture.h265.PicOrderCntVal[i] = 0; - } - - rps = priv->codec_data.h265.rps; - - if (rps) { - unsigned bf = 0, af = 0; - - priv->picture.h265.NumDeltaPocsOfRefRpsIdx = rps->num_delta_poc; - for (i = 0; i < rps->num_pics; ++i) { - priv->picture.h265.PicOrderCntVal[i] = - rps->delta_poc[i] + get_poc(priv); - - LIST_FOR_EACH_ENTRY(entry, &priv->codec_data.h265.dpb_list, list) { - if (entry->poc == priv->picture.h265.PicOrderCntVal[i]) { - priv->picture.h265.ref[i] = entry->buffer; - break; - } - } - - if (rps->used[i]) { - if (i < rps->num_neg_pics) { - priv->picture.h265.NumPocStCurrBefore++; - priv->picture.h265.RefPicSetStCurrBefore[bf++] = i; - } else { - priv->picture.h265.NumPocStCurrAfter++; - priv->picture.h265.RefPicSetStCurrAfter[af++] = i; - } - } - } - } - - priv->codec->end_frame(priv->codec, priv->target, &priv->picture.base); - priv->frame_started = false; - - /* add the decoded picture to the dpb list */ - entry = CALLOC_STRUCT(dpb_list); - if (!entry) - return; - - priv->first_buf_in_frame = true; - entry->buffer = priv->target; - entry->timestamp = priv->timestamp; - entry->poc = get_poc(priv); - - LIST_ADDTAIL(&entry->list, &priv->codec_data.h265.dpb_list); - ++priv->codec_data.h265.dpb_num; - priv->target = NULL; - - if (priv->codec_data.h265.dpb_num <= DPB_MAX_SIZE) - return; - - tmp = priv->in_buffers[0]->pInputPortPrivate; - priv->in_buffers[0]->pInputPortPrivate = vid_dec_h265_Flush(priv, ×tamp); - priv->in_buffers[0]->nTimeStamp = timestamp; - priv->target = tmp; - priv->frame_finished = priv->in_buffers[0]->pInputPortPrivate != NULL; - if (priv->frame_finished && - (priv->in_buffers[0]->nFlags & OMX_BUFFERFLAG_EOS)) - FREE(priv->codec_data.h265.ref_pic_set_list); -} - -static void slice_header(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, - unsigned nal_unit_type) -{ - struct pipe_h265_pps *pps; - struct pipe_h265_sps *sps; - bool first_slice_segment_in_pic_flag; - bool dependent_slice_segment_flag = false; - struct ref_pic_set *rps; - unsigned poc_lsb, poc_msb, slice_prev_poc; - unsigned max_poc_lsb, prev_poc_lsb, prev_poc_msb; - unsigned num_st_rps; - int i; - - if (priv->picture.h265.IDRPicFlag != is_idr_picture(nal_unit_type)) - vid_dec_h265_EndFrame(priv); - - priv->picture.h265.IDRPicFlag = is_idr_picture(nal_unit_type); - - first_slice_segment_in_pic_flag = vl_rbsp_u(rbsp, 1); - - if (is_rap_picture(nal_unit_type)) - /* no_output_of_prior_pics_flag */ - vl_rbsp_u(rbsp, 1); - - pps = pic_parameter_set_id(priv, rbsp); - if (!pps) - return; - - sps = pps->sps; - if (!sps) - return; - - if (pps != priv->picture.h265.pps) - vid_dec_h265_EndFrame(priv); - - priv->picture.h265.pps = pps; - - if (priv->picture.h265.RAPPicFlag != is_rap_picture(nal_unit_type)) - vid_dec_h265_EndFrame(priv); - priv->picture.h265.RAPPicFlag = is_rap_picture(nal_unit_type); - - num_st_rps = sps->num_short_term_ref_pic_sets; - - if (priv->picture.h265.CurrRpsIdx != num_st_rps) - vid_dec_h265_EndFrame(priv); - priv->picture.h265.CurrRpsIdx = num_st_rps; - - if (!first_slice_segment_in_pic_flag) { - int size, num; - int bits_slice_segment_address = 0; - - if (pps->dependent_slice_segments_enabled_flag) - dependent_slice_segment_flag = vl_rbsp_u(rbsp, 1); - - size = 1 << (sps->log2_min_luma_coding_block_size_minus3 + 3 + - sps->log2_diff_max_min_luma_coding_block_size); - - num = ((sps->pic_width_in_luma_samples + size - 1) / size) * - ((sps->pic_height_in_luma_samples + size - 1) / size); - - while (num > (1 << bits_slice_segment_address)) - bits_slice_segment_address++; - - /* slice_segment_address */ - vl_rbsp_u(rbsp, bits_slice_segment_address); - } - - if (dependent_slice_segment_flag) - return; - - for (i = 0; i < pps->num_extra_slice_header_bits; ++i) - /* slice_reserved_flag */ - vl_rbsp_u(rbsp, 1); - - /* slice_type */ - vl_rbsp_ue(rbsp); - - if (pps->output_flag_present_flag) - /* pic output flag */ - vl_rbsp_u(rbsp, 1); - - if (sps->separate_colour_plane_flag) - /* colour_plane_id */ - vl_rbsp_u(rbsp, 2); - - if (is_idr_picture(nal_unit_type)) { - set_poc(priv, nal_unit_type, 0); - return; - } - - /* slice_pic_order_cnt_lsb */ - poc_lsb = - vl_rbsp_u(rbsp, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); - - slice_prev_poc = (int)priv->codec_data.h265.slice_prev_poc; - max_poc_lsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); - - prev_poc_lsb = slice_prev_poc & (max_poc_lsb - 1); - prev_poc_msb = slice_prev_poc - prev_poc_lsb; - - if ((poc_lsb < prev_poc_lsb) && - ((prev_poc_lsb - poc_lsb ) >= (max_poc_lsb / 2))) - poc_msb = prev_poc_msb + max_poc_lsb; - - else if ((poc_lsb > prev_poc_lsb ) && - ((poc_lsb - prev_poc_lsb) > (max_poc_lsb / 2))) - poc_msb = prev_poc_msb - max_poc_lsb; - - else - poc_msb = prev_poc_msb; - - if (is_bla_picture(nal_unit_type)) - poc_msb = 0; - - if (get_poc(priv) != poc_msb + poc_lsb) - vid_dec_h265_EndFrame(priv); - - set_poc(priv, nal_unit_type, (poc_msb + poc_lsb)); - - /* short_term_ref_pic_set_sps_flag */ - if (!vl_rbsp_u(rbsp, 1)) { - rps = (struct ref_pic_set *) - priv->codec_data.h265.ref_pic_set_list + num_st_rps; - st_ref_pic_set(priv, rbsp, rps, sps, num_st_rps); - - } else if (num_st_rps > 1) { - int num_bits = 0; - unsigned idx; - - while ((1 << num_bits) < num_st_rps) - num_bits++; - - if (num_bits > 0) - /* short_term_ref_pic_set_idx */ - idx = vl_rbsp_u(rbsp, num_bits); - else - idx = 0; - - rps = (struct ref_pic_set *) - priv->codec_data.h265.ref_pic_set_list + idx; - } else - rps = (struct ref_pic_set *) - priv->codec_data.h265.ref_pic_set_list; - - if (is_bla_picture(nal_unit_type)) { - rps->num_neg_pics = 0; - rps->num_pos_pics = 0; - rps->num_pics = 0; - } - - priv->codec_data.h265.rps = rps; - - return; -} - -static void vid_dec_h265_Decode(vid_dec_PrivateType *priv, - struct vl_vlc *vlc, - unsigned min_bits_left) -{ - unsigned nal_unit_type; - unsigned nuh_layer_id; - unsigned nuh_temporal_id_plus1; - - if (!vl_vlc_search_byte(vlc, vl_vlc_bits_left(vlc) - min_bits_left, 0x00)) - return; - - if (vl_vlc_peekbits(vlc, 24) != 0x000001) { - vl_vlc_eatbits(vlc, 8); - return; - } - - if (priv->slice) { - unsigned bytes = priv->bytes_left - (vl_vlc_bits_left(vlc) / 8); - - priv->codec->decode_bitstream(priv->codec, priv->target, - &priv->picture.base, 1, - &priv->slice, &bytes); - priv->slice = NULL; - } - - vl_vlc_eatbits(vlc, 24); - - /* forbidden_zero_bit */ - vl_vlc_eatbits(vlc, 1); - - if (vl_vlc_valid_bits(vlc) < 15) - vl_vlc_fillbits(vlc); - - nal_unit_type = vl_vlc_get_uimsbf(vlc, 6); - - /* nuh_layer_id */ - nuh_layer_id = vl_vlc_get_uimsbf(vlc, 6); - - /* nuh_temporal_id_plus1 */ - nuh_temporal_id_plus1 = vl_vlc_get_uimsbf(vlc, 3); - priv->codec_data.h265.temporal_id = nuh_temporal_id_plus1 - 1; - - if (!is_slice_picture(nal_unit_type)) - vid_dec_h265_EndFrame(priv); - - if (nal_unit_type == NAL_UNIT_TYPE_SPS) { - struct vl_rbsp rbsp; - - vl_rbsp_init(&rbsp, vlc, ~0); - seq_parameter_set(priv, &rbsp); - - } else if (nal_unit_type == NAL_UNIT_TYPE_PPS) { - struct vl_rbsp rbsp; - - vl_rbsp_init(&rbsp, vlc, ~0); - picture_parameter_set(priv, &rbsp); - - } else if (is_slice_picture(nal_unit_type)) { - unsigned bits = vl_vlc_valid_bits(vlc); - unsigned bytes = bits / 8 + 5; - struct vl_rbsp rbsp; - uint8_t buf[9]; - const void *ptr = buf; - unsigned i; - - buf[0] = 0x0; - buf[1] = 0x0; - buf[2] = 0x1; - buf[3] = nal_unit_type << 1 | nuh_layer_id >> 5; - buf[4] = nuh_layer_id << 3 | nuh_temporal_id_plus1; - for (i = 5; i < bytes; ++i) - buf[i] = vl_vlc_peekbits(vlc, bits) >> ((bytes - i - 1) * 8); - - priv->bytes_left = (vl_vlc_bits_left(vlc) - bits) / 8; - priv->slice = vlc->data; - - vl_rbsp_init(&rbsp, vlc, 128); - slice_header(priv, &rbsp, nal_unit_type); - - vid_dec_h265_BeginFrame(priv); - - priv->codec->decode_bitstream(priv->codec, priv->target, - &priv->picture.base, 1, - &ptr, &bytes); - } - - /* resync to byte boundary */ - vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8); -} - -void vid_dec_h265_Init(vid_dec_PrivateType *priv) -{ - priv->picture.base.profile = PIPE_VIDEO_PROFILE_HEVC_MAIN; - - LIST_INITHEAD(&priv->codec_data.h265.dpb_list); - priv->codec_data.h265.ref_pic_set_list = (struct ref_pic_set *) - CALLOC(MAX_NUM_REF_PICS, sizeof(struct ref_pic_set)); - - priv->Decode = vid_dec_h265_Decode; - priv->EndFrame = vid_dec_h265_EndFrame; - priv->Flush = vid_dec_h265_Flush; - priv->first_buf_in_frame = true; -} diff --git a/src/gallium/state_trackers/omx/vid_dec_mpeg12.c b/src/gallium/state_trackers/omx/vid_dec_mpeg12.c deleted file mode 100644 index 7b2df8f40fa..00000000000 --- a/src/gallium/state_trackers/omx/vid_dec_mpeg12.c +++ /dev/null @@ -1,383 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* - * Authors: - * Christian König - * - */ - -#include "pipe/p_video_codec.h" -#include "vl/vl_vlc.h" -#include "vl/vl_zscan.h" - -#include "vid_dec.h" - -static uint8_t default_intra_matrix[64] = { - 8, 16, 19, 22, 26, 27, 29, 34, - 16, 16, 19, 22, 22, 22, 22, 26, - 26, 27, 22, 26, 26, 27, 29, 24, - 27, 27, 29, 32, 27, 29, 29, 32, - 35, 29, 34, 34, 35, 40, 34, 34, - 37, 40, 48, 37, 38, 40, 48, 58, - 26, 27, 29, 34, 38, 46, 56, 69, - 27, 29, 35, 38, 46, 56, 69, 83 -}; - -static uint8_t default_non_intra_matrix[64] = { - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16 -}; - -static void vid_dec_mpeg12_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left); -static void vid_dec_mpeg12_EndFrame(vid_dec_PrivateType *priv); -static struct pipe_video_buffer *vid_dec_mpeg12_Flush(vid_dec_PrivateType *priv, OMX_TICKS *timestamp); - -void vid_dec_mpeg12_Init(vid_dec_PrivateType *priv) -{ - struct pipe_video_codec templat = {}; - omx_base_video_PortType *port; - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; - templat.profile = priv->profile; - templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; - templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - templat.max_references = 2; - templat.expect_chunked_decode = true; - templat.width = port->sPortParam.format.video.nFrameWidth; - templat.height = port->sPortParam.format.video.nFrameHeight; - - priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat); - - priv->picture.base.profile = PIPE_VIDEO_PROFILE_MPEG2_MAIN; - priv->picture.mpeg12.intra_matrix = default_intra_matrix; - priv->picture.mpeg12.non_intra_matrix = default_non_intra_matrix; - - priv->Decode = vid_dec_mpeg12_Decode; - priv->EndFrame = vid_dec_mpeg12_EndFrame; - priv->Flush = vid_dec_mpeg12_Flush; -} - -static void BeginFrame(vid_dec_PrivateType *priv) -{ - if (priv->picture.mpeg12.picture_coding_type != PIPE_MPEG12_PICTURE_CODING_TYPE_B) { - priv->picture.mpeg12.ref[0] = priv->picture.mpeg12.ref[1]; - priv->picture.mpeg12.ref[1] = NULL; - } - - if (priv->target == priv->picture.mpeg12.ref[0]) { - struct pipe_video_buffer *tmp = priv->target; - priv->target = priv->shadow; - priv->shadow = tmp; - } - - vid_dec_NeedTarget(priv); - - priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base); - priv->frame_started = true; -} - -static void vid_dec_mpeg12_EndFrame(vid_dec_PrivateType *priv) -{ - struct pipe_video_buffer *done; - - priv->codec->end_frame(priv->codec, priv->target, &priv->picture.base); - priv->frame_started = false; - - if (priv->picture.mpeg12.picture_coding_type != PIPE_MPEG12_PICTURE_CODING_TYPE_B) { - - priv->picture.mpeg12.ref[1] = priv->target; - done = priv->picture.mpeg12.ref[0]; - if (!done) { - priv->target = NULL; - return; - } - - } else - done = priv->target; - - priv->frame_finished = true; - priv->target = priv->in_buffers[0]->pInputPortPrivate; - priv->in_buffers[0]->pInputPortPrivate = done; -} - -static struct pipe_video_buffer *vid_dec_mpeg12_Flush(vid_dec_PrivateType *priv, OMX_TICKS *timestamp) -{ - struct pipe_video_buffer *result = priv->picture.mpeg12.ref[1]; - priv->picture.mpeg12.ref[1] = NULL; - if (timestamp) - *timestamp = OMX_VID_DEC_TIMESTAMP_INVALID; - return result; -} - -static void vid_dec_mpeg12_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left) -{ - uint8_t code; - unsigned i; - - if (!vl_vlc_search_byte(vlc, vl_vlc_bits_left(vlc) - min_bits_left, 0x00)) - return; - - if (vl_vlc_peekbits(vlc, 24) != 0x000001) { - vl_vlc_eatbits(vlc, 8); - return; - } - - if (priv->slice) { - unsigned bytes = priv->bytes_left - (vl_vlc_bits_left(vlc) / 8); - priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, - 1, &priv->slice, &bytes); - priv->slice = NULL; - } - - vl_vlc_eatbits(vlc, 24); - code = vl_vlc_get_uimsbf(vlc, 8); - - if (priv->frame_started && (code == 0x00 || code > 0xAF)) - vid_dec_mpeg12_EndFrame(priv); - - if (code == 0xB3) { - /* sequence header code */ - vl_vlc_fillbits(vlc); - - /* horizontal_size_value */ - vl_vlc_get_uimsbf(vlc, 12); - - /* vertical_size_value */ - vl_vlc_get_uimsbf(vlc, 12); - - /* aspect_ratio_information */ - vl_vlc_get_uimsbf(vlc, 4); - - /* frame_rate_code */ - vl_vlc_get_uimsbf(vlc, 4); - - vl_vlc_fillbits(vlc); - - /* bit_rate_value */ - vl_vlc_get_uimsbf(vlc, 18); - - /* marker_bit */ - vl_vlc_get_uimsbf(vlc, 1); - - /* vbv_buffer_size_value */ - vl_vlc_get_uimsbf(vlc, 10); - - /* constrained_parameters_flag */ - vl_vlc_get_uimsbf(vlc, 1); - - vl_vlc_fillbits(vlc); - - /* load_intra_quantiser_matrix */ - if (vl_vlc_get_uimsbf(vlc, 1)) { - /* intra_quantiser_matrix */ - priv->picture.mpeg12.intra_matrix = priv->codec_data.mpeg12.intra_matrix; - for (i = 0; i < 64; ++i) { - priv->codec_data.mpeg12.intra_matrix[vl_zscan_normal[i]] = vl_vlc_get_uimsbf(vlc, 8); - vl_vlc_fillbits(vlc); - } - } else - priv->picture.mpeg12.intra_matrix = default_intra_matrix; - - /* load_non_intra_quantiser_matrix */ - if (vl_vlc_get_uimsbf(vlc, 1)) { - /* non_intra_quantiser_matrix */ - priv->picture.mpeg12.non_intra_matrix = priv->codec_data.mpeg12.non_intra_matrix; - for (i = 0; i < 64; ++i) { - priv->codec_data.mpeg12.non_intra_matrix[i] = vl_vlc_get_uimsbf(vlc, 8); - vl_vlc_fillbits(vlc); - } - } else - priv->picture.mpeg12.non_intra_matrix = default_non_intra_matrix; - - } else if (code == 0x00) { - /* picture start code */ - vl_vlc_fillbits(vlc); - - /* temporal_reference */ - vl_vlc_get_uimsbf(vlc, 10); - - priv->picture.mpeg12.picture_coding_type = vl_vlc_get_uimsbf(vlc, 3); - - /* vbv_delay */ - vl_vlc_get_uimsbf(vlc, 16); - - vl_vlc_fillbits(vlc); - if (priv->picture.mpeg12.picture_coding_type == 2 || - priv->picture.mpeg12.picture_coding_type == 3) { - priv->picture.mpeg12.full_pel_forward_vector = vl_vlc_get_uimsbf(vlc, 1); - /* forward_f_code */ - priv->picture.mpeg12.f_code[0][0] = vl_vlc_get_uimsbf(vlc, 3) - 1; - priv->picture.mpeg12.f_code[0][1] = priv->picture.mpeg12.f_code[0][0]; - } else { - priv->picture.mpeg12.full_pel_forward_vector = 0; - priv->picture.mpeg12.f_code[0][1] = priv->picture.mpeg12.f_code[0][0] = 14; - } - - if (priv->picture.mpeg12.picture_coding_type == 3) { - priv->picture.mpeg12.full_pel_backward_vector = vl_vlc_get_uimsbf(vlc, 1); - /* backward_f_code */ - priv->picture.mpeg12.f_code[1][0] = vl_vlc_get_uimsbf(vlc, 3) - 1; - priv->picture.mpeg12.f_code[1][1] = priv->picture.mpeg12.f_code[1][0]; - } else { - priv->picture.mpeg12.full_pel_backward_vector = 0; - priv->picture.mpeg12.f_code[0][1] = priv->picture.mpeg12.f_code[0][0] = 14; - } - - /* extra_bit_picture */ - while (vl_vlc_get_uimsbf(vlc, 1)) { - /* extra_information_picture */ - vl_vlc_get_uimsbf(vlc, 8); - vl_vlc_fillbits(vlc); - } - - } else if (code == 0xB5) { - /* extension start code */ - vl_vlc_fillbits(vlc); - - /* extension_start_code_identifier */ - switch (vl_vlc_get_uimsbf(vlc, 4)) { - case 0x3: /* quant matrix extension */ - - /* load_intra_quantiser_matrix */ - if (vl_vlc_get_uimsbf(vlc, 1)) { - /* intra_quantiser_matrix */ - priv->picture.mpeg12.intra_matrix = priv->codec_data.mpeg12.intra_matrix; - for (i = 0; i < 64; ++i) { - priv->codec_data.mpeg12.intra_matrix[vl_zscan_normal[i]] = vl_vlc_get_uimsbf(vlc, 8); - vl_vlc_fillbits(vlc); - } - } else - priv->picture.mpeg12.intra_matrix = default_intra_matrix; - - /* load_non_intra_quantiser_matrix */ - if (vl_vlc_get_uimsbf(vlc, 1)) { - /* non_intra_quantiser_matrix */ - priv->picture.mpeg12.non_intra_matrix = priv->codec_data.mpeg12.non_intra_matrix; - for (i = 0; i < 64; ++i) { - priv->codec_data.mpeg12.non_intra_matrix[i] = vl_vlc_get_uimsbf(vlc, 8); - vl_vlc_fillbits(vlc); - } - } else - priv->picture.mpeg12.intra_matrix = default_non_intra_matrix; - - break; - - case 0x8: /* picture coding extension */ - - priv->picture.mpeg12.f_code[0][0] = vl_vlc_get_uimsbf(vlc, 4) - 1; - priv->picture.mpeg12.f_code[0][1] = vl_vlc_get_uimsbf(vlc, 4) - 1; - priv->picture.mpeg12.f_code[1][0] = vl_vlc_get_uimsbf(vlc, 4) - 1; - priv->picture.mpeg12.f_code[1][1] = vl_vlc_get_uimsbf(vlc, 4) - 1; - priv->picture.mpeg12.intra_dc_precision = vl_vlc_get_uimsbf(vlc, 2); - priv->picture.mpeg12.picture_structure = vl_vlc_get_uimsbf(vlc, 2); - priv->picture.mpeg12.top_field_first = vl_vlc_get_uimsbf(vlc, 1); - priv->picture.mpeg12.frame_pred_frame_dct = vl_vlc_get_uimsbf(vlc, 1); - priv->picture.mpeg12.concealment_motion_vectors = vl_vlc_get_uimsbf(vlc, 1); - priv->picture.mpeg12.q_scale_type = vl_vlc_get_uimsbf(vlc, 1); - priv->picture.mpeg12.intra_vlc_format = vl_vlc_get_uimsbf(vlc, 1); - priv->picture.mpeg12.alternate_scan = vl_vlc_get_uimsbf(vlc, 1); - - /* repeat_first_field */ - vl_vlc_get_uimsbf(vlc, 1); - - /* chroma_420_type */ - vl_vlc_get_uimsbf(vlc, 1); - - vl_vlc_fillbits(vlc); - - /* progressive_frame */ - vl_vlc_get_uimsbf(vlc, 1); - - /* composite_display_flag */ - if (vl_vlc_get_uimsbf(vlc, 1)) { - - /* v_axis */ - vl_vlc_get_uimsbf(vlc, 1); - - /* field_sequence */ - vl_vlc_get_uimsbf(vlc, 3); - - /* sub_carrier */ - vl_vlc_get_uimsbf(vlc, 1); - - /* burst_amplitude */ - vl_vlc_get_uimsbf(vlc, 7); - - /* sub_carrier_phase */ - vl_vlc_get_uimsbf(vlc, 8); - } - break; - } - - } else if (code <= 0xAF) { - /* slice start */ - unsigned bytes = (vl_vlc_valid_bits(vlc) / 8) + 4; - uint8_t buf[12]; - const void *ptr = buf; - unsigned i; - - if (!priv->frame_started) - BeginFrame(priv); - - buf[0] = 0x00; - buf[1] = 0x00; - buf[2] = 0x01; - buf[3] = code; - for (i = 4; i < bytes; ++i) - buf[i] = vl_vlc_get_uimsbf(vlc, 8); - - priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, - 1, &ptr, &bytes); - - priv->bytes_left = vl_vlc_bits_left(vlc) / 8; - priv->slice = vlc->data; - - } else if (code == 0xB2) { - /* user data start */ - - } else if (code == 0xB4) { - /* sequence error */ - } else if (code == 0xB7) { - /* sequence end */ - } else if (code == 0xB8) { - /* group start */ - } else if (code >= 0xB9) { - /* system start */ - } else { - /* reserved */ - } - - /* resync to byte boundary */ - vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8); -} diff --git a/src/gallium/state_trackers/omx/vid_enc.c b/src/gallium/state_trackers/omx/vid_enc.c deleted file mode 100644 index 1a4fb62d408..00000000000 --- a/src/gallium/state_trackers/omx/vid_enc.c +++ /dev/null @@ -1,1278 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* - * Authors: - * Christian König - * - */ - - -#include - -#include - -/* bellagio defines a DEBUG macro that we don't want */ -#ifndef DEBUG -#include -#undef DEBUG -#else -#include -#endif - -#include - -#include "pipe/p_screen.h" -#include "pipe/p_video_codec.h" -#include "util/u_memory.h" -#include "vl/vl_video_buffer.h" - -#include "entrypoint.h" -#include "vid_enc.h" - -struct encode_task { - struct list_head list; - - struct pipe_video_buffer *buf; - unsigned pic_order_cnt; - struct pipe_resource *bitstream; - void *feedback; -}; - -struct input_buf_private { - struct list_head tasks; - - struct pipe_resource *resource; - struct pipe_transfer *transfer; -}; - -struct output_buf_private { - struct pipe_resource *bitstream; - struct pipe_transfer *transfer; -}; - -static OMX_ERRORTYPE vid_enc_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name); -static OMX_ERRORTYPE vid_enc_Destructor(OMX_COMPONENTTYPE *comp); -static OMX_ERRORTYPE vid_enc_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param); -static OMX_ERRORTYPE vid_enc_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param); -static OMX_ERRORTYPE vid_enc_SetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config); -static OMX_ERRORTYPE vid_enc_GetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config); -static OMX_ERRORTYPE vid_enc_MessageHandler(OMX_COMPONENTTYPE *comp, internalRequestMessageType *msg); -static OMX_ERRORTYPE vid_enc_AllocateInBuffer(omx_base_PortType *port, OMX_INOUT OMX_BUFFERHEADERTYPE **buf, - OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size); -static OMX_ERRORTYPE vid_enc_UseInBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE **buf, OMX_U32 idx, - OMX_PTR private, OMX_U32 size, OMX_U8 *mem); -static OMX_ERRORTYPE vid_enc_FreeInBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf); -static OMX_ERRORTYPE vid_enc_EncodeFrame(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf); -static OMX_ERRORTYPE vid_enc_AllocateOutBuffer(omx_base_PortType *comp, OMX_INOUT OMX_BUFFERHEADERTYPE **buf, - OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size); -static OMX_ERRORTYPE vid_enc_FreeOutBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf); -static void vid_enc_BufferEncoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output); - -static void enc_ReleaseTasks(struct list_head *head); - -OMX_ERRORTYPE vid_enc_LoaderComponent(stLoaderComponentType *comp) -{ - comp->componentVersion.s.nVersionMajor = 0; - comp->componentVersion.s.nVersionMinor = 0; - comp->componentVersion.s.nRevision = 0; - comp->componentVersion.s.nStep = 1; - comp->name_specific_length = 1; - comp->constructor = vid_enc_Constructor; - - comp->name = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); - if (!comp->name) - return OMX_ErrorInsufficientResources; - - comp->name_specific = CALLOC(1, sizeof(char *)); - if (!comp->name_specific) - goto error_arrays; - - comp->role_specific = CALLOC(1, sizeof(char *)); - if (!comp->role_specific) - goto error_arrays; - - comp->name_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); - if (comp->name_specific[0] == NULL) - goto error_specific; - - comp->role_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); - if (comp->role_specific[0] == NULL) - goto error_specific; - - strcpy(comp->name, OMX_VID_ENC_BASE_NAME); - strcpy(comp->name_specific[0], OMX_VID_ENC_AVC_NAME); - strcpy(comp->role_specific[0], OMX_VID_ENC_AVC_ROLE); - - return OMX_ErrorNone; - -error_specific: - FREE(comp->role_specific[0]); - FREE(comp->name_specific[0]); - -error_arrays: - FREE(comp->role_specific); - FREE(comp->name_specific); - - FREE(comp->name); - - return OMX_ErrorInsufficientResources; -} - -static OMX_ERRORTYPE vid_enc_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name) -{ - vid_enc_PrivateType *priv; - omx_base_video_PortType *port; - struct pipe_screen *screen; - OMX_ERRORTYPE r; - int i; - - assert(!comp->pComponentPrivate); - - priv = comp->pComponentPrivate = CALLOC(1, sizeof(vid_enc_PrivateType)); - if (!priv) - return OMX_ErrorInsufficientResources; - - r = omx_base_filter_Constructor(comp, name); - if (r) - return r; - - priv->BufferMgmtCallback = vid_enc_BufferEncoded; - priv->messageHandler = vid_enc_MessageHandler; - priv->destructor = vid_enc_Destructor; - - comp->SetParameter = vid_enc_SetParameter; - comp->GetParameter = vid_enc_GetParameter; - comp->GetConfig = vid_enc_GetConfig; - comp->SetConfig = vid_enc_SetConfig; - - priv->screen = omx_get_screen(); - if (!priv->screen) - return OMX_ErrorInsufficientResources; - - screen = priv->screen->pscreen; - if (!screen->get_video_param(screen, PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH, - PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_SUPPORTED)) - return OMX_ErrorBadParameter; - - priv->s_pipe = screen->context_create(screen, NULL, 0); - if (!priv->s_pipe) - return OMX_ErrorInsufficientResources; - - if (!vl_compositor_init(&priv->compositor, priv->s_pipe)) { - priv->s_pipe->destroy(priv->s_pipe); - priv->s_pipe = NULL; - return OMX_ErrorInsufficientResources; - } - - if (!vl_compositor_init_state(&priv->cstate, priv->s_pipe)) { - vl_compositor_cleanup(&priv->compositor); - priv->s_pipe->destroy(priv->s_pipe); - priv->s_pipe = NULL; - return OMX_ErrorInsufficientResources; - } - - priv->t_pipe = screen->context_create(screen, NULL, 0); - if (!priv->t_pipe) - return OMX_ErrorInsufficientResources; - - priv->sPortTypesParam[OMX_PortDomainVideo].nStartPortNumber = 0; - priv->sPortTypesParam[OMX_PortDomainVideo].nPorts = 2; - priv->ports = CALLOC(2, sizeof(omx_base_PortType *)); - if (!priv->ports) - return OMX_ErrorInsufficientResources; - - for (i = 0; i < 2; ++i) { - priv->ports[i] = CALLOC(1, sizeof(omx_base_video_PortType)); - if (!priv->ports[i]) - return OMX_ErrorInsufficientResources; - - base_video_port_Constructor(comp, &priv->ports[i], i, i == 0); - } - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; - port->sPortParam.format.video.nFrameWidth = 176; - port->sPortParam.format.video.nFrameHeight = 144; - port->sPortParam.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; - port->sVideoParam.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; - port->sPortParam.nBufferCountActual = 8; - port->sPortParam.nBufferCountMin = 4; - - port->Port_SendBufferFunction = vid_enc_EncodeFrame; - port->Port_AllocateBuffer = vid_enc_AllocateInBuffer; - port->Port_UseBuffer = vid_enc_UseInBuffer; - port->Port_FreeBuffer = vid_enc_FreeInBuffer; - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; - strcpy(port->sPortParam.format.video.cMIMEType,"video/H264"); - port->sPortParam.format.video.nFrameWidth = 176; - port->sPortParam.format.video.nFrameHeight = 144; - port->sPortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; - port->sVideoParam.eCompressionFormat = OMX_VIDEO_CodingAVC; - - port->Port_AllocateBuffer = vid_enc_AllocateOutBuffer; - port->Port_FreeBuffer = vid_enc_FreeOutBuffer; - - priv->bitrate.eControlRate = OMX_Video_ControlRateDisable; - priv->bitrate.nTargetBitrate = 0; - - priv->quant.nQpI = OMX_VID_ENC_QUANT_I_FRAMES_DEFAULT; - priv->quant.nQpP = OMX_VID_ENC_QUANT_P_FRAMES_DEFAULT; - priv->quant.nQpB = OMX_VID_ENC_QUANT_B_FRAMES_DEFAULT; - - priv->profile_level.eProfile = OMX_VIDEO_AVCProfileBaseline; - priv->profile_level.eLevel = OMX_VIDEO_AVCLevel51; - - priv->force_pic_type.IntraRefreshVOP = OMX_FALSE; - priv->frame_num = 0; - priv->pic_order_cnt = 0; - priv->restricted_b_frames = debug_get_bool_option("OMX_USE_RESTRICTED_B_FRAMES", FALSE); - - priv->scale.xWidth = OMX_VID_ENC_SCALING_WIDTH_DEFAULT; - priv->scale.xHeight = OMX_VID_ENC_SCALING_WIDTH_DEFAULT; - - LIST_INITHEAD(&priv->free_tasks); - LIST_INITHEAD(&priv->used_tasks); - LIST_INITHEAD(&priv->b_frames); - LIST_INITHEAD(&priv->stacked_tasks); - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_enc_Destructor(OMX_COMPONENTTYPE *comp) -{ - vid_enc_PrivateType* priv = comp->pComponentPrivate; - int i; - - enc_ReleaseTasks(&priv->free_tasks); - enc_ReleaseTasks(&priv->used_tasks); - enc_ReleaseTasks(&priv->b_frames); - enc_ReleaseTasks(&priv->stacked_tasks); - - if (priv->ports) { - for (i = 0; i < priv->sPortTypesParam[OMX_PortDomainVideo].nPorts; ++i) { - if(priv->ports[i]) - priv->ports[i]->PortDestructor(priv->ports[i]); - } - FREE(priv->ports); - priv->ports=NULL; - } - - for (i = 0; i < OMX_VID_ENC_NUM_SCALING_BUFFERS; ++i) - if (priv->scale_buffer[i]) - priv->scale_buffer[i]->destroy(priv->scale_buffer[i]); - - if (priv->s_pipe) { - vl_compositor_cleanup_state(&priv->cstate); - vl_compositor_cleanup(&priv->compositor); - priv->s_pipe->destroy(priv->s_pipe); - } - - if (priv->t_pipe) - priv->t_pipe->destroy(priv->t_pipe); - - if (priv->screen) - omx_put_screen(); - - return omx_workaround_Destructor(comp); -} - -static OMX_ERRORTYPE enc_AllocateBackTexture(omx_base_PortType *port, - struct pipe_resource **resource, - struct pipe_transfer **transfer, - OMX_U8 **map) -{ - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - struct pipe_resource buf_templ; - struct pipe_box box = {}; - OMX_U8 *ptr; - - memset(&buf_templ, 0, sizeof buf_templ); - buf_templ.target = PIPE_TEXTURE_2D; - buf_templ.format = PIPE_FORMAT_I8_UNORM; - buf_templ.bind = PIPE_BIND_LINEAR; - buf_templ.usage = PIPE_USAGE_STAGING; - buf_templ.flags = 0; - buf_templ.width0 = port->sPortParam.format.video.nFrameWidth; - buf_templ.height0 = port->sPortParam.format.video.nFrameHeight * 3 / 2; - buf_templ.depth0 = 1; - buf_templ.array_size = 1; - - *resource = priv->s_pipe->screen->resource_create(priv->s_pipe->screen, &buf_templ); - if (!*resource) - return OMX_ErrorInsufficientResources; - - box.width = (*resource)->width0; - box.height = (*resource)->height0; - box.depth = (*resource)->depth0; - ptr = priv->s_pipe->transfer_map(priv->s_pipe, *resource, 0, PIPE_TRANSFER_WRITE, &box, transfer); - if (map) - *map = ptr; - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_enc_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param) -{ - OMX_COMPONENTTYPE *comp = handle; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - OMX_ERRORTYPE r; - - if (!param) - return OMX_ErrorBadParameter; - - switch(idx) { - case OMX_IndexParamPortDefinition: { - OMX_PARAM_PORTDEFINITIONTYPE *def = param; - - r = omx_base_component_SetParameter(handle, idx, param); - if (r) - return r; - - if (def->nPortIndex == OMX_BASE_FILTER_INPUTPORT_INDEX) { - omx_base_video_PortType *port; - unsigned framesize; - struct pipe_resource *resource; - struct pipe_transfer *transfer; - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; - enc_AllocateBackTexture(priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX], - &resource, &transfer, NULL); - port->sPortParam.format.video.nStride = transfer->stride; - pipe_transfer_unmap(priv->s_pipe, transfer); - pipe_resource_reference(&resource, NULL); - - framesize = port->sPortParam.format.video.nStride * - port->sPortParam.format.video.nFrameHeight; - port->sPortParam.format.video.nSliceHeight = port->sPortParam.format.video.nFrameHeight; - port->sPortParam.nBufferSize = framesize * 3 / 2; - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; - port->sPortParam.nBufferSize = framesize * 512 / (16*16); - - priv->frame_rate = def->format.video.xFramerate; - - priv->callbacks->EventHandler(comp, priv->callbackData, OMX_EventPortSettingsChanged, - OMX_BASE_FILTER_OUTPUTPORT_INDEX, 0, NULL); - } - break; - } - case OMX_IndexParamStandardComponentRole: { - OMX_PARAM_COMPONENTROLETYPE *role = param; - - r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE)); - if (r) - return r; - - if (strcmp((char *)role->cRole, OMX_VID_ENC_AVC_ROLE)) { - return OMX_ErrorBadParameter; - } - - break; - } - case OMX_IndexParamVideoBitrate: { - OMX_VIDEO_PARAM_BITRATETYPE *bitrate = param; - - r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_BITRATETYPE)); - if (r) - return r; - - priv->bitrate = *bitrate; - - break; - } - case OMX_IndexParamVideoQuantization: { - OMX_VIDEO_PARAM_QUANTIZATIONTYPE *quant = param; - - r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_QUANTIZATIONTYPE)); - if (r) - return r; - - priv->quant = *quant; - - break; - } - case OMX_IndexParamVideoProfileLevelCurrent: { - OMX_VIDEO_PARAM_PROFILELEVELTYPE *profile_level = param; - - r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); - if (r) - return r; - - priv->profile_level = *profile_level; - - break; - } - default: - return omx_base_component_SetParameter(handle, idx, param); - } - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_enc_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param) -{ - OMX_COMPONENTTYPE *comp = handle; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - OMX_ERRORTYPE r; - - if (!param) - return OMX_ErrorBadParameter; - - switch(idx) { - case OMX_IndexParamStandardComponentRole: { - OMX_PARAM_COMPONENTROLETYPE *role = param; - - r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE)); - if (r) - return r; - - strcpy((char *)role->cRole, OMX_VID_ENC_AVC_ROLE); - break; - } - case OMX_IndexParamVideoInit: - r = checkHeader(param, sizeof(OMX_PORT_PARAM_TYPE)); - if (r) - return r; - - memcpy(param, &priv->sPortTypesParam[OMX_PortDomainVideo], sizeof(OMX_PORT_PARAM_TYPE)); - break; - - case OMX_IndexParamVideoPortFormat: { - OMX_VIDEO_PARAM_PORTFORMATTYPE *format = param; - omx_base_video_PortType *port; - - r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); - if (r) - return r; - - if (format->nPortIndex > 1) - return OMX_ErrorBadPortIndex; - if (format->nIndex >= 1) - return OMX_ErrorNoMore; - - port = (omx_base_video_PortType *)priv->ports[format->nPortIndex]; - memcpy(format, &port->sVideoParam, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); - break; - } - case OMX_IndexParamVideoBitrate: { - OMX_VIDEO_PARAM_BITRATETYPE *bitrate = param; - - r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_BITRATETYPE)); - if (r) - return r; - - bitrate->eControlRate = priv->bitrate.eControlRate; - bitrate->nTargetBitrate = priv->bitrate.nTargetBitrate; - - break; - } - case OMX_IndexParamVideoQuantization: { - OMX_VIDEO_PARAM_QUANTIZATIONTYPE *quant = param; - - r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_QUANTIZATIONTYPE)); - if (r) - return r; - - quant->nQpI = priv->quant.nQpI; - quant->nQpP = priv->quant.nQpP; - quant->nQpB = priv->quant.nQpB; - - break; - } - case OMX_IndexParamVideoProfileLevelCurrent: { - OMX_VIDEO_PARAM_PROFILELEVELTYPE *profile_level = param; - - r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); - if (r) - return r; - - profile_level->eProfile = priv->profile_level.eProfile; - profile_level->eLevel = priv->profile_level.eLevel; - - break; - } - default: - return omx_base_component_GetParameter(handle, idx, param); - } - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_enc_SetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config) -{ - OMX_COMPONENTTYPE *comp = handle; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - OMX_ERRORTYPE r; - int i; - - if (!config) - return OMX_ErrorBadParameter; - - switch(idx) { - case OMX_IndexConfigVideoIntraVOPRefresh: { - OMX_CONFIG_INTRAREFRESHVOPTYPE *type = config; - - r = checkHeader(config, sizeof(OMX_CONFIG_INTRAREFRESHVOPTYPE)); - if (r) - return r; - - priv->force_pic_type = *type; - - break; - } - case OMX_IndexConfigCommonScale: { - OMX_CONFIG_SCALEFACTORTYPE *scale = config; - - r = checkHeader(config, sizeof(OMX_CONFIG_SCALEFACTORTYPE)); - if (r) - return r; - - if (scale->xWidth < 176 || scale->xHeight < 144) - return OMX_ErrorBadParameter; - - for (i = 0; i < OMX_VID_ENC_NUM_SCALING_BUFFERS; ++i) { - if (priv->scale_buffer[i]) { - priv->scale_buffer[i]->destroy(priv->scale_buffer[i]); - priv->scale_buffer[i] = NULL; - } - } - - priv->scale = *scale; - if (priv->scale.xWidth != 0xffffffff && priv->scale.xHeight != 0xffffffff) { - struct pipe_video_buffer templat = {}; - - templat.buffer_format = PIPE_FORMAT_NV12; - templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - templat.width = priv->scale.xWidth; - templat.height = priv->scale.xHeight; - templat.interlaced = false; - for (i = 0; i < OMX_VID_ENC_NUM_SCALING_BUFFERS; ++i) { - priv->scale_buffer[i] = priv->s_pipe->create_video_buffer(priv->s_pipe, &templat); - if (!priv->scale_buffer[i]) - return OMX_ErrorInsufficientResources; - } - } - - break; - } - default: - return omx_base_component_SetConfig(handle, idx, config); - } - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_enc_GetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config) -{ - OMX_COMPONENTTYPE *comp = handle; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - OMX_ERRORTYPE r; - - if (!config) - return OMX_ErrorBadParameter; - - switch(idx) { - case OMX_IndexConfigCommonScale: { - OMX_CONFIG_SCALEFACTORTYPE *scale = config; - - r = checkHeader(config, sizeof(OMX_CONFIG_SCALEFACTORTYPE)); - if (r) - return r; - - scale->xWidth = priv->scale.xWidth; - scale->xHeight = priv->scale.xHeight; - - break; - } - default: - return omx_base_component_GetConfig(handle, idx, config); - } - - return OMX_ErrorNone; -} - -static enum pipe_video_profile enc_TranslateOMXProfileToPipe(unsigned omx_profile) -{ - switch (omx_profile) { - case OMX_VIDEO_AVCProfileBaseline: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE; - case OMX_VIDEO_AVCProfileMain: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN; - case OMX_VIDEO_AVCProfileExtended: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_EXTENDED; - case OMX_VIDEO_AVCProfileHigh: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; - case OMX_VIDEO_AVCProfileHigh10: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10; - case OMX_VIDEO_AVCProfileHigh422: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH422; - case OMX_VIDEO_AVCProfileHigh444: - return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH444; - default: - return PIPE_VIDEO_PROFILE_UNKNOWN; - } -} - -static unsigned enc_TranslateOMXLevelToPipe(unsigned omx_level) -{ - switch (omx_level) { - case OMX_VIDEO_AVCLevel1: - case OMX_VIDEO_AVCLevel1b: - return 10; - case OMX_VIDEO_AVCLevel11: - return 11; - case OMX_VIDEO_AVCLevel12: - return 12; - case OMX_VIDEO_AVCLevel13: - return 13; - case OMX_VIDEO_AVCLevel2: - return 20; - case OMX_VIDEO_AVCLevel21: - return 21; - case OMX_VIDEO_AVCLevel22: - return 22; - case OMX_VIDEO_AVCLevel3: - return 30; - case OMX_VIDEO_AVCLevel31: - return 31; - case OMX_VIDEO_AVCLevel32: - return 32; - case OMX_VIDEO_AVCLevel4: - return 40; - case OMX_VIDEO_AVCLevel41: - return 41; - default: - case OMX_VIDEO_AVCLevel42: - return 42; - case OMX_VIDEO_AVCLevel5: - return 50; - case OMX_VIDEO_AVCLevel51: - return 51; - } -} - -static OMX_ERRORTYPE vid_enc_MessageHandler(OMX_COMPONENTTYPE* comp, internalRequestMessageType *msg) -{ - vid_enc_PrivateType* priv = comp->pComponentPrivate; - - if (msg->messageType == OMX_CommandStateSet) { - if ((msg->messageParam == OMX_StateIdle ) && (priv->state == OMX_StateLoaded)) { - - struct pipe_video_codec templat = {}; - omx_base_video_PortType *port; - - port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; - - templat.profile = enc_TranslateOMXProfileToPipe(priv->profile_level.eProfile); - templat.level = enc_TranslateOMXLevelToPipe(priv->profile_level.eLevel); - templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_ENCODE; - templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - templat.width = priv->scale_buffer[priv->current_scale_buffer] ? - priv->scale.xWidth : port->sPortParam.format.video.nFrameWidth; - templat.height = priv->scale_buffer[priv->current_scale_buffer] ? - priv->scale.xHeight : port->sPortParam.format.video.nFrameHeight; - - if (templat.profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE) { - struct pipe_screen *screen = priv->screen->pscreen; - templat.max_references = 1; - priv->stacked_frames_num = - screen->get_video_param(screen, - PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH, - PIPE_VIDEO_ENTRYPOINT_ENCODE, - PIPE_VIDEO_CAP_STACKED_FRAMES); - } else { - templat.max_references = OMX_VID_ENC_P_PERIOD_DEFAULT; - priv->stacked_frames_num = 1; - } - priv->codec = priv->s_pipe->create_video_codec(priv->s_pipe, &templat); - - } else if ((msg->messageParam == OMX_StateLoaded) && (priv->state == OMX_StateIdle)) { - if (priv->codec) { - priv->codec->destroy(priv->codec); - priv->codec = NULL; - } - } - } - - return omx_base_component_MessageHandler(comp, msg); -} - -static OMX_ERRORTYPE vid_enc_AllocateInBuffer(omx_base_PortType *port, OMX_INOUT OMX_BUFFERHEADERTYPE **buf, - OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size) -{ - struct input_buf_private *inp; - OMX_ERRORTYPE r; - - r = base_port_AllocateBuffer(port, buf, idx, private, size); - if (r) - return r; - - inp = (*buf)->pInputPortPrivate = CALLOC_STRUCT(input_buf_private); - if (!inp) { - base_port_FreeBuffer(port, idx, *buf); - return OMX_ErrorInsufficientResources; - } - - LIST_INITHEAD(&inp->tasks); - - FREE((*buf)->pBuffer); - r = enc_AllocateBackTexture(port, &inp->resource, &inp->transfer, &(*buf)->pBuffer); - if (r) { - FREE(inp); - base_port_FreeBuffer(port, idx, *buf); - return r; - } - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_enc_UseInBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE **buf, OMX_U32 idx, - OMX_PTR private, OMX_U32 size, OMX_U8 *mem) -{ - struct input_buf_private *inp; - OMX_ERRORTYPE r; - - r = base_port_UseBuffer(port, buf, idx, private, size, mem); - if (r) - return r; - - inp = (*buf)->pInputPortPrivate = CALLOC_STRUCT(input_buf_private); - if (!inp) { - base_port_FreeBuffer(port, idx, *buf); - return OMX_ErrorInsufficientResources; - } - - LIST_INITHEAD(&inp->tasks); - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_enc_FreeInBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf) -{ - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - struct input_buf_private *inp = buf->pInputPortPrivate; - - if (inp) { - enc_ReleaseTasks(&inp->tasks); - if (inp->transfer) - pipe_transfer_unmap(priv->s_pipe, inp->transfer); - pipe_resource_reference(&inp->resource, NULL); - FREE(inp); - } - buf->pBuffer = NULL; - - return base_port_FreeBuffer(port, idx, buf); -} - -static OMX_ERRORTYPE vid_enc_AllocateOutBuffer(omx_base_PortType *port, OMX_INOUT OMX_BUFFERHEADERTYPE **buf, - OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size) -{ - OMX_ERRORTYPE r; - - r = base_port_AllocateBuffer(port, buf, idx, private, size); - if (r) - return r; - - FREE((*buf)->pBuffer); - (*buf)->pBuffer = NULL; - (*buf)->pOutputPortPrivate = CALLOC(1, sizeof(struct output_buf_private)); - if (!(*buf)->pOutputPortPrivate) { - base_port_FreeBuffer(port, idx, *buf); - return OMX_ErrorInsufficientResources; - } - - return OMX_ErrorNone; -} - -static OMX_ERRORTYPE vid_enc_FreeOutBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf) -{ - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - - if (buf->pOutputPortPrivate) { - struct output_buf_private *outp = buf->pOutputPortPrivate; - if (outp->transfer) - pipe_transfer_unmap(priv->t_pipe, outp->transfer); - pipe_resource_reference(&outp->bitstream, NULL); - FREE(outp); - buf->pOutputPortPrivate = NULL; - } - buf->pBuffer = NULL; - - return base_port_FreeBuffer(port, idx, buf); -} - -static struct encode_task *enc_NeedTask(omx_base_PortType *port) -{ - OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - - struct pipe_video_buffer templat = {}; - struct encode_task *task; - - if (!LIST_IS_EMPTY(&priv->free_tasks)) { - task = LIST_ENTRY(struct encode_task, priv->free_tasks.next, list); - LIST_DEL(&task->list); - return task; - } - - /* allocate a new one */ - task = CALLOC_STRUCT(encode_task); - if (!task) - return NULL; - - templat.buffer_format = PIPE_FORMAT_NV12; - templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; - templat.width = def->nFrameWidth; - templat.height = def->nFrameHeight; - templat.interlaced = false; - - task->buf = priv->s_pipe->create_video_buffer(priv->s_pipe, &templat); - if (!task->buf) { - FREE(task); - return NULL; - } - - return task; -} - -static void enc_MoveTasks(struct list_head *from, struct list_head *to) -{ - to->prev->next = from->next; - from->next->prev = to->prev; - from->prev->next = to; - to->prev = from->prev; - LIST_INITHEAD(from); -} - -static void enc_ReleaseTasks(struct list_head *head) -{ - struct encode_task *i, *next; - - if (!head || !head->next) - return; - - LIST_FOR_EACH_ENTRY_SAFE(i, next, head, list) { - pipe_resource_reference(&i->bitstream, NULL); - i->buf->destroy(i->buf); - FREE(i); - } -} - -static OMX_ERRORTYPE enc_LoadImage(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf, - struct pipe_video_buffer *vbuf) -{ - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; - struct pipe_box box = {}; - struct input_buf_private *inp = buf->pInputPortPrivate; - - if (!inp->resource) { - struct pipe_sampler_view **views; - void *ptr; - - views = vbuf->get_sampler_view_planes(vbuf); - if (!views) - return OMX_ErrorInsufficientResources; - - ptr = buf->pBuffer; - box.width = def->nFrameWidth; - box.height = def->nFrameHeight; - box.depth = 1; - priv->s_pipe->texture_subdata(priv->s_pipe, views[0]->texture, 0, - PIPE_TRANSFER_WRITE, &box, - ptr, def->nStride, 0); - ptr = ((uint8_t*)buf->pBuffer) + (def->nStride * box.height); - box.width = def->nFrameWidth / 2; - box.height = def->nFrameHeight / 2; - box.depth = 1; - priv->s_pipe->texture_subdata(priv->s_pipe, views[1]->texture, 0, - PIPE_TRANSFER_WRITE, &box, - ptr, def->nStride, 0); - } else { - struct pipe_blit_info blit; - struct vl_video_buffer *dst_buf = (struct vl_video_buffer *)vbuf; - - pipe_transfer_unmap(priv->s_pipe, inp->transfer); - - box.width = def->nFrameWidth; - box.height = def->nFrameHeight; - box.depth = 1; - - priv->s_pipe->resource_copy_region(priv->s_pipe, - dst_buf->resources[0], - 0, 0, 0, 0, inp->resource, 0, &box); - - memset(&blit, 0, sizeof(blit)); - blit.src.resource = inp->resource; - blit.src.format = inp->resource->format; - - blit.src.box.x = 0; - blit.src.box.y = def->nFrameHeight; - blit.src.box.width = def->nFrameWidth; - blit.src.box.height = def->nFrameHeight / 2 ; - blit.src.box.depth = 1; - - blit.dst.resource = dst_buf->resources[1]; - blit.dst.format = blit.dst.resource->format; - - blit.dst.box.width = def->nFrameWidth / 2; - blit.dst.box.height = def->nFrameHeight / 2; - blit.dst.box.depth = 1; - blit.filter = PIPE_TEX_FILTER_NEAREST; - - blit.mask = PIPE_MASK_G; - priv->s_pipe->blit(priv->s_pipe, &blit); - - blit.src.box.x = 1; - blit.mask = PIPE_MASK_R; - priv->s_pipe->blit(priv->s_pipe, &blit); - priv->s_pipe->flush(priv->s_pipe, NULL, 0); - - box.width = inp->resource->width0; - box.height = inp->resource->height0; - box.depth = inp->resource->depth0; - buf->pBuffer = priv->s_pipe->transfer_map(priv->s_pipe, inp->resource, 0, - PIPE_TRANSFER_WRITE, &box, - &inp->transfer); - } - - return OMX_ErrorNone; -} - -static void enc_ScaleInput(omx_base_PortType *port, struct pipe_video_buffer **vbuf, unsigned *size) -{ - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; - struct pipe_video_buffer *src_buf = *vbuf; - struct vl_compositor *compositor = &priv->compositor; - struct vl_compositor_state *s = &priv->cstate; - struct pipe_sampler_view **views; - struct pipe_surface **dst_surface; - unsigned i; - - if (!priv->scale_buffer[priv->current_scale_buffer]) - return; - - views = src_buf->get_sampler_view_planes(src_buf); - dst_surface = priv->scale_buffer[priv->current_scale_buffer]->get_surfaces - (priv->scale_buffer[priv->current_scale_buffer]); - vl_compositor_clear_layers(s); - - for (i = 0; i < VL_MAX_SURFACES; ++i) { - struct u_rect src_rect; - if (!views[i] || !dst_surface[i]) - continue; - src_rect.x0 = 0; - src_rect.y0 = 0; - src_rect.x1 = def->nFrameWidth; - src_rect.y1 = def->nFrameHeight; - if (i > 0) { - src_rect.x1 /= 2; - src_rect.y1 /= 2; - } - vl_compositor_set_rgba_layer(s, compositor, 0, views[i], &src_rect, NULL, NULL); - vl_compositor_render(s, compositor, dst_surface[i], NULL, false); - } - *size = priv->scale.xWidth * priv->scale.xHeight * 2; - *vbuf = priv->scale_buffer[priv->current_scale_buffer++]; - priv->current_scale_buffer %= OMX_VID_ENC_NUM_SCALING_BUFFERS; -} - -static void enc_GetPictureParamPreset(struct pipe_h264_enc_picture_desc *picture) -{ - picture->motion_est.enc_disable_sub_mode = 0x000000fe; - picture->motion_est.enc_ime2_search_range_x = 0x00000001; - picture->motion_est.enc_ime2_search_range_y = 0x00000001; - picture->pic_ctrl.enc_constraint_set_flags = 0x00000040; -} - -static void enc_ControlPicture(omx_base_PortType *port, struct pipe_h264_enc_picture_desc *picture) -{ - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - struct pipe_h264_enc_rate_control *rate_ctrl = &picture->rate_ctrl; - - switch (priv->bitrate.eControlRate) { - case OMX_Video_ControlRateVariable: - rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_VARIABLE; - break; - case OMX_Video_ControlRateConstant: - rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_CONSTANT; - break; - case OMX_Video_ControlRateVariableSkipFrames: - rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_VARIABLE_SKIP; - break; - case OMX_Video_ControlRateConstantSkipFrames: - rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_CONSTANT_SKIP; - break; - default: - rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_DISABLE; - break; - } - - rate_ctrl->frame_rate_den = OMX_VID_ENC_CONTROL_FRAME_RATE_DEN_DEFAULT; - rate_ctrl->frame_rate_num = ((priv->frame_rate) >> 16) * rate_ctrl->frame_rate_den; - - if (rate_ctrl->rate_ctrl_method != PIPE_H264_ENC_RATE_CONTROL_METHOD_DISABLE) { - if (priv->bitrate.nTargetBitrate < OMX_VID_ENC_BITRATE_MIN) - rate_ctrl->target_bitrate = OMX_VID_ENC_BITRATE_MIN; - else if (priv->bitrate.nTargetBitrate < OMX_VID_ENC_BITRATE_MAX) - rate_ctrl->target_bitrate = priv->bitrate.nTargetBitrate; - else - rate_ctrl->target_bitrate = OMX_VID_ENC_BITRATE_MAX; - rate_ctrl->peak_bitrate = rate_ctrl->target_bitrate; - if (rate_ctrl->target_bitrate < OMX_VID_ENC_BITRATE_MEDIAN) - rate_ctrl->vbv_buffer_size = MIN2((rate_ctrl->target_bitrate * 2.75), OMX_VID_ENC_BITRATE_MEDIAN); - else - rate_ctrl->vbv_buffer_size = rate_ctrl->target_bitrate; - - if (rate_ctrl->frame_rate_num) { - unsigned long long t = rate_ctrl->target_bitrate; - t *= rate_ctrl->frame_rate_den; - rate_ctrl->target_bits_picture = t / rate_ctrl->frame_rate_num; - } else { - rate_ctrl->target_bits_picture = rate_ctrl->target_bitrate; - } - rate_ctrl->peak_bits_picture_integer = rate_ctrl->target_bits_picture; - rate_ctrl->peak_bits_picture_fraction = 0; - } - - picture->quant_i_frames = priv->quant.nQpI; - picture->quant_p_frames = priv->quant.nQpP; - picture->quant_b_frames = priv->quant.nQpB; - - picture->frame_num = priv->frame_num; - picture->ref_idx_l0 = priv->ref_idx_l0; - picture->ref_idx_l1 = priv->ref_idx_l1; - picture->enable_vui = (picture->rate_ctrl.frame_rate_num != 0); - enc_GetPictureParamPreset(picture); -} - -static void enc_HandleTask(omx_base_PortType *port, struct encode_task *task, - enum pipe_h264_enc_picture_type picture_type) -{ - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - unsigned size = priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]->sPortParam.nBufferSize; - struct pipe_video_buffer *vbuf = task->buf; - struct pipe_h264_enc_picture_desc picture = {}; - - /* -------------- scale input image --------- */ - enc_ScaleInput(port, &vbuf, &size); - priv->s_pipe->flush(priv->s_pipe, NULL, 0); - - /* -------------- allocate output buffer --------- */ - task->bitstream = pipe_buffer_create(priv->s_pipe->screen, - PIPE_BIND_VERTEX_BUFFER, - PIPE_USAGE_STAGING, /* map for read */ - size); - - picture.picture_type = picture_type; - picture.pic_order_cnt = task->pic_order_cnt; - if (priv->restricted_b_frames && picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) - picture.not_referenced = true; - enc_ControlPicture(port, &picture); - - /* -------------- encode frame --------- */ - priv->codec->begin_frame(priv->codec, vbuf, &picture.base); - priv->codec->encode_bitstream(priv->codec, vbuf, task->bitstream, &task->feedback); - priv->codec->end_frame(priv->codec, vbuf, &picture.base); -} - -static void enc_ClearBframes(omx_base_PortType *port, struct input_buf_private *inp) -{ - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - struct encode_task *task; - - if (LIST_IS_EMPTY(&priv->b_frames)) - return; - - task = LIST_ENTRY(struct encode_task, priv->b_frames.prev, list); - LIST_DEL(&task->list); - - /* promote last from to P frame */ - priv->ref_idx_l0 = priv->ref_idx_l1; - enc_HandleTask(port, task, PIPE_H264_ENC_PICTURE_TYPE_P); - LIST_ADDTAIL(&task->list, &inp->tasks); - priv->ref_idx_l1 = priv->frame_num++; - - /* handle B frames */ - LIST_FOR_EACH_ENTRY(task, &priv->b_frames, list) { - enc_HandleTask(port, task, PIPE_H264_ENC_PICTURE_TYPE_B); - if (!priv->restricted_b_frames) - priv->ref_idx_l0 = priv->frame_num; - priv->frame_num++; - } - - enc_MoveTasks(&priv->b_frames, &inp->tasks); -} - -static OMX_ERRORTYPE vid_enc_EncodeFrame(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf) -{ - OMX_COMPONENTTYPE* comp = port->standCompContainer; - vid_enc_PrivateType *priv = comp->pComponentPrivate; - struct input_buf_private *inp = buf->pInputPortPrivate; - enum pipe_h264_enc_picture_type picture_type; - struct encode_task *task; - unsigned stacked_num = 0; - OMX_ERRORTYPE err; - - enc_MoveTasks(&inp->tasks, &priv->free_tasks); - task = enc_NeedTask(port); - if (!task) - return OMX_ErrorInsufficientResources; - - if (buf->nFilledLen == 0) { - if (buf->nFlags & OMX_BUFFERFLAG_EOS) { - buf->nFilledLen = buf->nAllocLen; - enc_ClearBframes(port, inp); - enc_MoveTasks(&priv->stacked_tasks, &inp->tasks); - priv->codec->flush(priv->codec); - } - return base_port_SendBufferFunction(port, buf); - } - - if (buf->pOutputPortPrivate) { - struct pipe_video_buffer *vbuf = buf->pOutputPortPrivate; - buf->pOutputPortPrivate = task->buf; - task->buf = vbuf; - } else { - /* ------- load input image into video buffer ---- */ - err = enc_LoadImage(port, buf, task->buf); - if (err != OMX_ErrorNone) { - FREE(task); - return err; - } - } - - /* -------------- determine picture type --------- */ - if (!(priv->pic_order_cnt % OMX_VID_ENC_IDR_PERIOD_DEFAULT) || - priv->force_pic_type.IntraRefreshVOP) { - enc_ClearBframes(port, inp); - picture_type = PIPE_H264_ENC_PICTURE_TYPE_IDR; - priv->force_pic_type.IntraRefreshVOP = OMX_FALSE; - priv->frame_num = 0; - } else if (priv->codec->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE || - !(priv->pic_order_cnt % OMX_VID_ENC_P_PERIOD_DEFAULT) || - (buf->nFlags & OMX_BUFFERFLAG_EOS)) { - picture_type = PIPE_H264_ENC_PICTURE_TYPE_P; - } else { - picture_type = PIPE_H264_ENC_PICTURE_TYPE_B; - } - - task->pic_order_cnt = priv->pic_order_cnt++; - - if (picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) { - /* put frame at the tail of the queue */ - LIST_ADDTAIL(&task->list, &priv->b_frames); - } else { - /* handle I or P frame */ - priv->ref_idx_l0 = priv->ref_idx_l1; - enc_HandleTask(port, task, picture_type); - LIST_ADDTAIL(&task->list, &priv->stacked_tasks); - LIST_FOR_EACH_ENTRY(task, &priv->stacked_tasks, list) { - ++stacked_num; - } - if (stacked_num == priv->stacked_frames_num) { - struct encode_task *t; - t = LIST_ENTRY(struct encode_task, priv->stacked_tasks.next, list); - LIST_DEL(&t->list); - LIST_ADDTAIL(&t->list, &inp->tasks); - } - priv->ref_idx_l1 = priv->frame_num++; - - /* handle B frames */ - LIST_FOR_EACH_ENTRY(task, &priv->b_frames, list) { - enc_HandleTask(port, task, PIPE_H264_ENC_PICTURE_TYPE_B); - if (!priv->restricted_b_frames) - priv->ref_idx_l0 = priv->frame_num; - priv->frame_num++; - } - - enc_MoveTasks(&priv->b_frames, &inp->tasks); - } - - if (LIST_IS_EMPTY(&inp->tasks)) - return port->ReturnBufferFunction(port, buf); - else - return base_port_SendBufferFunction(port, buf); -} - -static void vid_enc_BufferEncoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output) -{ - vid_enc_PrivateType *priv = comp->pComponentPrivate; - struct output_buf_private *outp = output->pOutputPortPrivate; - struct input_buf_private *inp = input->pInputPortPrivate; - struct encode_task *task; - struct pipe_box box = {}; - unsigned size; - - if (!inp || LIST_IS_EMPTY(&inp->tasks)) { - input->nFilledLen = 0; /* mark buffer as empty */ - enc_MoveTasks(&priv->used_tasks, &inp->tasks); - return; - } - - task = LIST_ENTRY(struct encode_task, inp->tasks.next, list); - LIST_DEL(&task->list); - LIST_ADDTAIL(&task->list, &priv->used_tasks); - - if (!task->bitstream) - return; - - /* ------------- map result buffer ----------------- */ - - if (outp->transfer) - pipe_transfer_unmap(priv->t_pipe, outp->transfer); - - pipe_resource_reference(&outp->bitstream, task->bitstream); - pipe_resource_reference(&task->bitstream, NULL); - - box.width = outp->bitstream->width0; - box.height = outp->bitstream->height0; - box.depth = outp->bitstream->depth0; - - output->pBuffer = priv->t_pipe->transfer_map(priv->t_pipe, outp->bitstream, 0, - PIPE_TRANSFER_READ_WRITE, - &box, &outp->transfer); - - /* ------------- get size of result ----------------- */ - - priv->codec->get_feedback(priv->codec, task->feedback, &size); - - output->nOffset = 0; - output->nFilledLen = size; /* mark buffer as full */ - - /* all output buffers contain exactly one frame */ - output->nFlags = OMX_BUFFERFLAG_ENDOFFRAME; -} diff --git a/src/gallium/state_trackers/omx/vid_enc.h b/src/gallium/state_trackers/omx/vid_enc.h deleted file mode 100644 index a83374450b5..00000000000 --- a/src/gallium/state_trackers/omx/vid_enc.h +++ /dev/null @@ -1,96 +0,0 @@ -/************************************************************************** - * - * Copyright 2013 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/* - * Authors: - * Christian König - * - */ - -#ifndef OMX_VID_ENC_H -#define OMX_VID_ENC_H - -#include -#include -#include - -#include -#include - -#include "util/list.h" - -#include "vl/vl_defines.h" -#include "vl/vl_compositor.h" - -#define OMX_VID_ENC_BASE_NAME "OMX.mesa.video_encoder" -#define OMX_VID_ENC_AVC_NAME "OMX.mesa.video_encoder.avc" -#define OMX_VID_ENC_AVC_ROLE "video_encoder.avc" - -#define OMX_VID_ENC_BITRATE_MIN 64000 -#define OMX_VID_ENC_BITRATE_MEDIAN 2000000 -#define OMX_VID_ENC_BITRATE_MAX 240000000 -#define OMX_VID_ENC_CONTROL_FRAME_RATE_DEN_DEFAULT 1001 -#define OMX_VID_ENC_QUANT_I_FRAMES_DEFAULT 0x1c -#define OMX_VID_ENC_QUANT_P_FRAMES_DEFAULT 0x1c -#define OMX_VID_ENC_QUANT_B_FRAMES_DEFAULT 0x1c -#define OMX_VID_ENC_SCALING_WIDTH_DEFAULT 0xffffffff -#define OMX_VID_ENC_SCALING_HEIGHT_DEFAULT 0xffffffff -#define OMX_VID_ENC_IDR_PERIOD_DEFAULT 1000 -#define OMX_VID_ENC_P_PERIOD_DEFAULT 3 - -#define OMX_VID_ENC_NUM_SCALING_BUFFERS 4 - -DERIVEDCLASS(vid_enc_PrivateType, omx_base_filter_PrivateType) -#define vid_enc_PrivateType_FIELDS omx_base_filter_PrivateType_FIELDS \ - struct vl_screen *screen; \ - struct pipe_context *s_pipe; \ - struct pipe_context *t_pipe; \ - struct pipe_video_codec *codec; \ - struct list_head free_tasks; \ - struct list_head used_tasks; \ - struct list_head b_frames; \ - struct list_head stacked_tasks; \ - OMX_U32 frame_rate; \ - OMX_U32 frame_num; \ - OMX_U32 pic_order_cnt; \ - OMX_U32 ref_idx_l0, ref_idx_l1; \ - OMX_BOOL restricted_b_frames; \ - OMX_VIDEO_PARAM_BITRATETYPE bitrate; \ - OMX_VIDEO_PARAM_QUANTIZATIONTYPE quant; \ - OMX_VIDEO_PARAM_PROFILELEVELTYPE profile_level; \ - OMX_CONFIG_INTRAREFRESHVOPTYPE force_pic_type; \ - struct vl_compositor compositor; \ - struct vl_compositor_state cstate; \ - struct pipe_video_buffer *scale_buffer[OMX_VID_ENC_NUM_SCALING_BUFFERS]; \ - OMX_CONFIG_SCALEFACTORTYPE scale; \ - OMX_U32 current_scale_buffer; \ - OMX_U32 stacked_frames_num; -ENDCLASS(vid_enc_PrivateType) - -OMX_ERRORTYPE vid_enc_LoaderComponent(stLoaderComponentType *comp); - -#endif diff --git a/src/gallium/state_trackers/omx_bellagio/Makefile.am b/src/gallium/state_trackers/omx_bellagio/Makefile.am new file mode 100644 index 00000000000..fcd8b2c310e --- /dev/null +++ b/src/gallium/state_trackers/omx_bellagio/Makefile.am @@ -0,0 +1,35 @@ +# Copyright © 2012 Intel Corporation +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +include Makefile.sources +include $(top_srcdir)/src/gallium/Automake.inc + +AM_CFLAGS = \ + $(GALLIUM_CFLAGS) \ + $(VISIBILITY_CFLAGS) \ + $(VL_CFLAGS) \ + $(XCB_DRI3_CFLAGS) \ + $(OMX_BELLAGIO_CFLAGS) + +noinst_LTLIBRARIES = libomxtracker.la + +libomxtracker_la_SOURCES = $(C_SOURCES) diff --git a/src/gallium/state_trackers/omx_bellagio/Makefile.sources b/src/gallium/state_trackers/omx_bellagio/Makefile.sources new file mode 100644 index 00000000000..ab60ce803cb --- /dev/null +++ b/src/gallium/state_trackers/omx_bellagio/Makefile.sources @@ -0,0 +1,10 @@ +C_SOURCES := \ + entrypoint.c \ + entrypoint.h \ + vid_dec.c \ + vid_dec.h \ + vid_dec_mpeg12.c \ + vid_dec_h264.c \ + vid_dec_h265.c \ + vid_enc.c \ + vid_enc.h diff --git a/src/gallium/state_trackers/omx_bellagio/entrypoint.c b/src/gallium/state_trackers/omx_bellagio/entrypoint.c new file mode 100644 index 00000000000..251cc7d65d5 --- /dev/null +++ b/src/gallium/state_trackers/omx_bellagio/entrypoint.c @@ -0,0 +1,152 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Authors: + * Christian König + * + */ + +#include +#include +#include + +#if defined(HAVE_X11_PLATFORM) +#include +#else +#define XOpenDisplay(x) NULL +#define XCloseDisplay(x) +#define Display void +#endif + +#include "os/os_thread.h" +#include "util/u_memory.h" +#include "loader/loader.h" + +#include "entrypoint.h" +#include "vid_dec.h" +#include "vid_enc.h" + +static mtx_t omx_lock = _MTX_INITIALIZER_NP; +static Display *omx_display = NULL; +static struct vl_screen *omx_screen = NULL; +static unsigned omx_usecount = 0; +static const char *omx_render_node = NULL; +static int drm_fd; + +int omx_component_library_Setup(stLoaderComponentType **stComponents) +{ + OMX_ERRORTYPE r; + + if (stComponents == NULL) + return 2; + + /* component 0 - video decoder */ + r = vid_dec_LoaderComponent(stComponents[0]); + if (r != OMX_ErrorNone) + return OMX_ErrorInsufficientResources; + + /* component 1 - video encoder */ + r = vid_enc_LoaderComponent(stComponents[1]); + if (r != OMX_ErrorNone) + return OMX_ErrorInsufficientResources; + + return 2; +} + +struct vl_screen *omx_get_screen(void) +{ + static bool first_time = true; + mtx_lock(&omx_lock); + + if (!omx_screen) { + if (first_time) { + omx_render_node = debug_get_option("OMX_RENDER_NODE", NULL); + first_time = false; + } + if (omx_render_node) { + drm_fd = loader_open_device(omx_render_node); + if (drm_fd < 0) + goto error; + + omx_screen = vl_drm_screen_create(drm_fd); + if (!omx_screen) { + close(drm_fd); + goto error; + } + } else { + omx_display = XOpenDisplay(NULL); + if (!omx_display) + goto error; + + omx_screen = vl_dri3_screen_create(omx_display, 0); + if (!omx_screen) + omx_screen = vl_dri2_screen_create(omx_display, 0); + if (!omx_screen) { + XCloseDisplay(omx_display); + goto error; + } + } + } + + ++omx_usecount; + + mtx_unlock(&omx_lock); + return omx_screen; + +error: + mtx_unlock(&omx_lock); + return NULL; +} + +void omx_put_screen(void) +{ + mtx_lock(&omx_lock); + if ((--omx_usecount) == 0) { + omx_screen->destroy(omx_screen); + omx_screen = NULL; + + if (omx_render_node) + close(drm_fd); + else + XCloseDisplay(omx_display); + } + mtx_unlock(&omx_lock); +} + +OMX_ERRORTYPE omx_workaround_Destructor(OMX_COMPONENTTYPE *comp) +{ + omx_base_component_PrivateType* priv = (omx_base_component_PrivateType*)comp->pComponentPrivate; + + priv->state = OMX_StateInvalid; + tsem_up(priv->messageSem); + + /* wait for thread to exit */ + pthread_join(priv->messageHandlerThread, NULL); + + return omx_base_component_Destructor(comp); +} diff --git a/src/gallium/state_trackers/omx_bellagio/entrypoint.h b/src/gallium/state_trackers/omx_bellagio/entrypoint.h new file mode 100644 index 00000000000..7625d7a5b03 --- /dev/null +++ b/src/gallium/state_trackers/omx_bellagio/entrypoint.h @@ -0,0 +1,48 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Authors: + * Christian König + * + */ + +#ifndef OMX_ENTRYPOINT_H +#define OMX_ENTRYPOINT_H + +#include + +#include "vl/vl_winsys.h" + +PUBLIC extern int omx_component_library_Setup(stLoaderComponentType **stComponents); + +struct vl_screen *omx_get_screen(void); +void omx_put_screen(void); + +OMX_ERRORTYPE omx_workaround_Destructor(OMX_COMPONENTTYPE *comp); + +#endif diff --git a/src/gallium/state_trackers/omx_bellagio/vid_dec.c b/src/gallium/state_trackers/omx_bellagio/vid_dec.c new file mode 100644 index 00000000000..28741c09a42 --- /dev/null +++ b/src/gallium/state_trackers/omx_bellagio/vid_dec.c @@ -0,0 +1,637 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Authors: + * Christian König + * + */ + + +#include + +#include + +/* bellagio defines a DEBUG macro that we don't want */ +#ifndef DEBUG +#include +#undef DEBUG +#else +#include +#endif + +#include "pipe/p_screen.h" +#include "pipe/p_video_codec.h" +#include "util/u_memory.h" +#include "util/u_surface.h" +#include "vl/vl_video_buffer.h" +#include "vl/vl_vlc.h" + +#include "entrypoint.h" +#include "vid_dec.h" + +static OMX_ERRORTYPE vid_dec_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name); +static OMX_ERRORTYPE vid_dec_Destructor(OMX_COMPONENTTYPE *comp); +static OMX_ERRORTYPE vid_dec_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param); +static OMX_ERRORTYPE vid_dec_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param); +static OMX_ERRORTYPE vid_dec_MessageHandler(OMX_COMPONENTTYPE *comp, internalRequestMessageType *msg); +static OMX_ERRORTYPE vid_dec_DecodeBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf); +static OMX_ERRORTYPE vid_dec_FreeDecBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf); +static void vid_dec_FrameDecoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output); + +OMX_ERRORTYPE vid_dec_LoaderComponent(stLoaderComponentType *comp) +{ + comp->componentVersion.s.nVersionMajor = 0; + comp->componentVersion.s.nVersionMinor = 0; + comp->componentVersion.s.nRevision = 0; + comp->componentVersion.s.nStep = 1; + comp->name_specific_length = 3; + + comp->name = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); + if (comp->name == NULL) + goto error; + + comp->name_specific = CALLOC(comp->name_specific_length, sizeof(char *)); + if (comp->name_specific == NULL) + goto error; + + comp->role_specific = CALLOC(comp->name_specific_length, sizeof(char *)); + if (comp->role_specific == NULL) + goto error; + + comp->name_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); + if (comp->name_specific[0] == NULL) + goto error_specific; + + comp->name_specific[1] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); + if (comp->name_specific[1] == NULL) + goto error_specific; + + comp->name_specific[2] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); + if (comp->name_specific[2] == NULL) + goto error_specific; + + comp->role_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); + if (comp->role_specific[0] == NULL) + goto error_specific; + + comp->role_specific[1] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); + if (comp->role_specific[1] == NULL) + goto error_specific; + + comp->role_specific[2] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); + if (comp->role_specific[2] == NULL) + goto error_specific; + + strcpy(comp->name, OMX_VID_DEC_BASE_NAME); + strcpy(comp->name_specific[0], OMX_VID_DEC_MPEG2_NAME); + strcpy(comp->name_specific[1], OMX_VID_DEC_AVC_NAME); + strcpy(comp->name_specific[2], OMX_VID_DEC_HEVC_NAME); + + strcpy(comp->role_specific[0], OMX_VID_DEC_MPEG2_ROLE); + strcpy(comp->role_specific[1], OMX_VID_DEC_AVC_ROLE); + strcpy(comp->role_specific[2], OMX_VID_DEC_HEVC_ROLE); + + comp->constructor = vid_dec_Constructor; + + return OMX_ErrorNone; + +error_specific: + FREE(comp->role_specific[2]); + FREE(comp->role_specific[1]); + FREE(comp->role_specific[0]); + FREE(comp->name_specific[2]); + FREE(comp->name_specific[1]); + FREE(comp->name_specific[0]); + +error: + FREE(comp->role_specific); + FREE(comp->name_specific); + + FREE(comp->name); + + return OMX_ErrorInsufficientResources; +} + +static OMX_ERRORTYPE vid_dec_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name) +{ + vid_dec_PrivateType *priv; + omx_base_video_PortType *port; + struct pipe_screen *screen; + OMX_ERRORTYPE r; + int i; + + assert(!comp->pComponentPrivate); + + priv = comp->pComponentPrivate = CALLOC(1, sizeof(vid_dec_PrivateType)); + if (!priv) + return OMX_ErrorInsufficientResources; + + r = omx_base_filter_Constructor(comp, name); + if (r) + return r; + + priv->profile = PIPE_VIDEO_PROFILE_UNKNOWN; + + if (!strcmp(name, OMX_VID_DEC_MPEG2_NAME)) + priv->profile = PIPE_VIDEO_PROFILE_MPEG2_MAIN; + + if (!strcmp(name, OMX_VID_DEC_AVC_NAME)) + priv->profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; + + if (!strcmp(name, OMX_VID_DEC_HEVC_NAME)) + priv->profile = PIPE_VIDEO_PROFILE_HEVC_MAIN; + + priv->BufferMgmtCallback = vid_dec_FrameDecoded; + priv->messageHandler = vid_dec_MessageHandler; + priv->destructor = vid_dec_Destructor; + + comp->SetParameter = vid_dec_SetParameter; + comp->GetParameter = vid_dec_GetParameter; + + priv->screen = omx_get_screen(); + if (!priv->screen) + return OMX_ErrorInsufficientResources; + + screen = priv->screen->pscreen; + priv->pipe = screen->context_create(screen, NULL, 0); + if (!priv->pipe) + return OMX_ErrorInsufficientResources; + + if (!vl_compositor_init(&priv->compositor, priv->pipe)) { + priv->pipe->destroy(priv->pipe); + priv->pipe = NULL; + return OMX_ErrorInsufficientResources; + } + + if (!vl_compositor_init_state(&priv->cstate, priv->pipe)) { + vl_compositor_cleanup(&priv->compositor); + priv->pipe->destroy(priv->pipe); + priv->pipe = NULL; + return OMX_ErrorInsufficientResources; + } + + priv->sPortTypesParam[OMX_PortDomainVideo].nStartPortNumber = 0; + priv->sPortTypesParam[OMX_PortDomainVideo].nPorts = 2; + priv->ports = CALLOC(2, sizeof(omx_base_PortType *)); + if (!priv->ports) + return OMX_ErrorInsufficientResources; + + for (i = 0; i < 2; ++i) { + priv->ports[i] = CALLOC(1, sizeof(omx_base_video_PortType)); + if (!priv->ports[i]) + return OMX_ErrorInsufficientResources; + + base_video_port_Constructor(comp, &priv->ports[i], i, i == 0); + } + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; + strcpy(port->sPortParam.format.video.cMIMEType,"video/MPEG2"); + port->sPortParam.nBufferCountMin = 8; + port->sPortParam.nBufferCountActual = 8; + port->sPortParam.nBufferSize = DEFAULT_OUT_BUFFER_SIZE; + port->sPortParam.format.video.nFrameWidth = 176; + port->sPortParam.format.video.nFrameHeight = 144; + port->sPortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG2; + port->sVideoParam.eCompressionFormat = OMX_VIDEO_CodingMPEG2; + port->Port_SendBufferFunction = vid_dec_DecodeBuffer; + port->Port_FreeBuffer = vid_dec_FreeDecBuffer; + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; + port->sPortParam.nBufferCountActual = 8; + port->sPortParam.nBufferCountMin = 4; + port->sPortParam.format.video.nFrameWidth = 176; + port->sPortParam.format.video.nFrameHeight = 144; + port->sPortParam.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + port->sVideoParam.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_dec_Destructor(OMX_COMPONENTTYPE *comp) +{ + vid_dec_PrivateType* priv = comp->pComponentPrivate; + int i; + + if (priv->ports) { + for (i = 0; i < priv->sPortTypesParam[OMX_PortDomainVideo].nPorts; ++i) { + if(priv->ports[i]) + priv->ports[i]->PortDestructor(priv->ports[i]); + } + FREE(priv->ports); + priv->ports=NULL; + } + + if (priv->pipe) { + vl_compositor_cleanup_state(&priv->cstate); + vl_compositor_cleanup(&priv->compositor); + priv->pipe->destroy(priv->pipe); + } + + if (priv->screen) + omx_put_screen(); + + return omx_workaround_Destructor(comp); +} + +static OMX_ERRORTYPE vid_dec_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param) +{ + OMX_COMPONENTTYPE *comp = handle; + vid_dec_PrivateType *priv = comp->pComponentPrivate; + OMX_ERRORTYPE r; + + if (!param) + return OMX_ErrorBadParameter; + + switch(idx) { + case OMX_IndexParamPortDefinition: { + OMX_PARAM_PORTDEFINITIONTYPE *def = param; + + r = omx_base_component_SetParameter(handle, idx, param); + if (r) + return r; + + if (def->nPortIndex == OMX_BASE_FILTER_INPUTPORT_INDEX) { + omx_base_video_PortType *port; + unsigned framesize = def->format.video.nFrameWidth * def->format.video.nFrameHeight; + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; + port->sPortParam.nBufferSize = framesize * 512 / (16*16); + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; + port->sPortParam.format.video.nFrameWidth = def->format.video.nFrameWidth; + port->sPortParam.format.video.nFrameHeight = def->format.video.nFrameHeight; + port->sPortParam.format.video.nStride = def->format.video.nFrameWidth; + port->sPortParam.format.video.nSliceHeight = def->format.video.nFrameHeight; + port->sPortParam.nBufferSize = framesize*3/2; + + priv->callbacks->EventHandler(comp, priv->callbackData, OMX_EventPortSettingsChanged, + OMX_BASE_FILTER_OUTPUTPORT_INDEX, 0, NULL); + } + break; + } + case OMX_IndexParamStandardComponentRole: { + OMX_PARAM_COMPONENTROLETYPE *role = param; + + r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (r) + return r; + + if (!strcmp((char *)role->cRole, OMX_VID_DEC_MPEG2_ROLE)) { + priv->profile = PIPE_VIDEO_PROFILE_MPEG2_MAIN; + } else if (!strcmp((char *)role->cRole, OMX_VID_DEC_AVC_ROLE)) { + priv->profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; + } else if (!strcmp((char *)role->cRole, OMX_VID_DEC_HEVC_ROLE)) { + priv->profile = PIPE_VIDEO_PROFILE_HEVC_MAIN; + } else { + return OMX_ErrorBadParameter; + } + + break; + } + case OMX_IndexParamVideoPortFormat: { + OMX_VIDEO_PARAM_PORTFORMATTYPE *format = param; + omx_base_video_PortType *port; + + r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + if (r) + return r; + + if (format->nPortIndex > 1) + return OMX_ErrorBadPortIndex; + + port = (omx_base_video_PortType *)priv->ports[format->nPortIndex]; + memcpy(&port->sVideoParam, format, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + break; + } + default: + return omx_base_component_SetParameter(handle, idx, param); + } + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_dec_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param) +{ + OMX_COMPONENTTYPE *comp = handle; + vid_dec_PrivateType *priv = comp->pComponentPrivate; + OMX_ERRORTYPE r; + + if (!param) + return OMX_ErrorBadParameter; + + switch(idx) { + case OMX_IndexParamStandardComponentRole: { + OMX_PARAM_COMPONENTROLETYPE *role = param; + + r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (r) + return r; + + if (priv->profile == PIPE_VIDEO_PROFILE_MPEG2_MAIN) + strcpy((char *)role->cRole, OMX_VID_DEC_MPEG2_ROLE); + else if (priv->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH) + strcpy((char *)role->cRole, OMX_VID_DEC_AVC_ROLE); + else if (priv->profile == PIPE_VIDEO_PROFILE_HEVC_MAIN) + strcpy((char *)role->cRole, OMX_VID_DEC_HEVC_ROLE); + + break; + } + + case OMX_IndexParamVideoInit: + r = checkHeader(param, sizeof(OMX_PORT_PARAM_TYPE)); + if (r) + return r; + + memcpy(param, &priv->sPortTypesParam[OMX_PortDomainVideo], sizeof(OMX_PORT_PARAM_TYPE)); + break; + + case OMX_IndexParamVideoPortFormat: { + OMX_VIDEO_PARAM_PORTFORMATTYPE *format = param; + omx_base_video_PortType *port; + + r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + if (r) + return r; + + if (format->nPortIndex > 1) + return OMX_ErrorBadPortIndex; + + port = (omx_base_video_PortType *)priv->ports[format->nPortIndex]; + memcpy(format, &port->sVideoParam, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + break; + } + + default: + return omx_base_component_GetParameter(handle, idx, param); + + } + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_dec_MessageHandler(OMX_COMPONENTTYPE* comp, internalRequestMessageType *msg) +{ + vid_dec_PrivateType* priv = comp->pComponentPrivate; + + if (msg->messageType == OMX_CommandStateSet) { + if ((msg->messageParam == OMX_StateIdle ) && (priv->state == OMX_StateLoaded)) { + if (priv->profile == PIPE_VIDEO_PROFILE_MPEG2_MAIN) + vid_dec_mpeg12_Init(priv); + else if (priv->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH) + vid_dec_h264_Init(priv); + else if (priv->profile == PIPE_VIDEO_PROFILE_HEVC_MAIN) + vid_dec_h265_Init(priv); + + } else if ((msg->messageParam == OMX_StateLoaded) && (priv->state == OMX_StateIdle)) { + if (priv->shadow) { + priv->shadow->destroy(priv->shadow); + priv->shadow = NULL; + } + if (priv->codec) { + priv->codec->destroy(priv->codec); + priv->codec = NULL; + } + } + } + + return omx_base_component_MessageHandler(comp, msg); +} + +void vid_dec_NeedTarget(vid_dec_PrivateType *priv) +{ + struct pipe_video_buffer templat = {}; + struct vl_screen *omx_screen; + struct pipe_screen *pscreen; + + omx_screen = priv->screen; + assert(omx_screen); + + pscreen = omx_screen->pscreen; + assert(pscreen); + + if (!priv->target) { + memset(&templat, 0, sizeof(templat)); + + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + templat.width = priv->codec->width; + templat.height = priv->codec->height; + templat.buffer_format = pscreen->get_video_param( + pscreen, + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_PREFERED_FORMAT + ); + templat.interlaced = pscreen->get_video_param( + pscreen, + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CAP_PREFERS_INTERLACED + ); + priv->target = priv->pipe->create_video_buffer(priv->pipe, &templat); + } +} + +static void vid_dec_FreeInputPortPrivate(OMX_BUFFERHEADERTYPE *buf) +{ + struct pipe_video_buffer *vbuf = buf->pInputPortPrivate; + if (!vbuf) + return; + + vbuf->destroy(vbuf); + buf->pInputPortPrivate = NULL; +} + +static OMX_ERRORTYPE vid_dec_DecodeBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf) +{ + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_dec_PrivateType *priv = comp->pComponentPrivate; + unsigned i = priv->num_in_buffers++; + OMX_ERRORTYPE r; + + priv->in_buffers[i] = buf; + priv->sizes[i] = buf->nFilledLen; + priv->inputs[i] = buf->pBuffer; + priv->timestamps[i] = buf->nTimeStamp; + + while (priv->num_in_buffers > (!!(buf->nFlags & OMX_BUFFERFLAG_EOS) ? 0 : 1)) { + bool eos = !!(priv->in_buffers[0]->nFlags & OMX_BUFFERFLAG_EOS); + unsigned min_bits_left = eos ? 32 : MAX2(buf->nFilledLen * 8, 32); + struct vl_vlc vlc; + + vl_vlc_init(&vlc, priv->num_in_buffers, priv->inputs, priv->sizes); + + if (priv->slice) + priv->bytes_left = vl_vlc_bits_left(&vlc) / 8; + + while (vl_vlc_bits_left(&vlc) > min_bits_left) { + priv->Decode(priv, &vlc, min_bits_left); + vl_vlc_fillbits(&vlc); + } + + if (priv->slice) { + unsigned bytes = priv->bytes_left - vl_vlc_bits_left(&vlc) / 8; + + priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, + 1, &priv->slice, &bytes); + + if (priv->num_in_buffers) + priv->slice = priv->inputs[1]; + else + priv->slice = NULL; + } + + if (eos && priv->frame_started) + priv->EndFrame(priv); + + if (priv->frame_finished) { + priv->frame_finished = false; + priv->in_buffers[0]->nFilledLen = priv->in_buffers[0]->nAllocLen; + r = base_port_SendBufferFunction(port, priv->in_buffers[0]); + } else if (eos) { + vid_dec_FreeInputPortPrivate(priv->in_buffers[0]); + priv->in_buffers[0]->nFilledLen = priv->in_buffers[0]->nAllocLen; + r = base_port_SendBufferFunction(port, priv->in_buffers[0]); + } else { + priv->in_buffers[0]->nFilledLen = 0; + r = port->ReturnBufferFunction(port, priv->in_buffers[0]); + } + + if (--priv->num_in_buffers) { + unsigned delta = MIN2((min_bits_left - vl_vlc_bits_left(&vlc)) / 8, priv->sizes[1]); + + priv->in_buffers[0] = priv->in_buffers[1]; + priv->sizes[0] = priv->sizes[1] - delta; + priv->inputs[0] = priv->inputs[1] + delta; + priv->timestamps[0] = priv->timestamps[1]; + } + + if (r) + return r; + } + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_dec_FreeDecBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf) +{ + vid_dec_FreeInputPortPrivate(buf); + return base_port_FreeBuffer(port, idx, buf); +} + +static void vid_dec_FillOutput(vid_dec_PrivateType *priv, struct pipe_video_buffer *buf, + OMX_BUFFERHEADERTYPE* output) +{ + omx_base_PortType *port = priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; + OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; + + struct pipe_sampler_view **views; + unsigned i, j; + unsigned width, height; + + views = buf->get_sampler_view_planes(buf); + + for (i = 0; i < 2 /* NV12 */; i++) { + if (!views[i]) continue; + width = def->nFrameWidth; + height = def->nFrameHeight; + vl_video_buffer_adjust_size(&width, &height, i, buf->chroma_format, buf->interlaced); + for (j = 0; j < views[i]->texture->array_size; ++j) { + struct pipe_box box = {0, 0, j, width, height, 1}; + struct pipe_transfer *transfer; + uint8_t *map, *dst; + map = priv->pipe->transfer_map(priv->pipe, views[i]->texture, 0, + PIPE_TRANSFER_READ, &box, &transfer); + if (!map) + return; + + dst = ((uint8_t*)output->pBuffer + output->nOffset) + j * def->nStride + + i * def->nFrameWidth * def->nFrameHeight; + util_copy_rect(dst, + views[i]->texture->format, + def->nStride * views[i]->texture->array_size, 0, 0, + box.width, box.height, map, transfer->stride, 0, 0); + + pipe_transfer_unmap(priv->pipe, transfer); + } + } +} + +static void vid_dec_FrameDecoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, + OMX_BUFFERHEADERTYPE* output) +{ + vid_dec_PrivateType *priv = comp->pComponentPrivate; + bool eos = !!(input->nFlags & OMX_BUFFERFLAG_EOS); + OMX_TICKS timestamp; + + if (!input->pInputPortPrivate) { + input->pInputPortPrivate = priv->Flush(priv, ×tamp); + if (timestamp != OMX_VID_DEC_TIMESTAMP_INVALID) + input->nTimeStamp = timestamp; + } + + if (input->pInputPortPrivate) { + if (output->pInputPortPrivate && !priv->disable_tunnel) { + struct pipe_video_buffer *tmp, *vbuf, *new_vbuf; + + tmp = output->pOutputPortPrivate; + vbuf = input->pInputPortPrivate; + if (vbuf->interlaced) { + /* re-allocate the progressive buffer */ + omx_base_video_PortType *port; + struct pipe_video_buffer templat = {}; + + port = (omx_base_video_PortType *) + priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; + memset(&templat, 0, sizeof(templat)); + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + templat.width = port->sPortParam.format.video.nFrameWidth; + templat.height = port->sPortParam.format.video.nFrameHeight; + templat.buffer_format = PIPE_FORMAT_NV12; + templat.interlaced = false; + new_vbuf = priv->pipe->create_video_buffer(priv->pipe, &templat); + + /* convert the interlaced to the progressive */ + vl_compositor_yuv_deint(&priv->cstate, &priv->compositor, + input->pInputPortPrivate, new_vbuf); + + /* set the progrssive buffer for next round */ + vbuf->destroy(vbuf); + input->pInputPortPrivate = new_vbuf; + } + output->pOutputPortPrivate = input->pInputPortPrivate; + input->pInputPortPrivate = tmp; + } else { + vid_dec_FillOutput(priv, input->pInputPortPrivate, output); + } + output->nFilledLen = output->nAllocLen; + output->nTimeStamp = input->nTimeStamp; + } + + if (eos && input->pInputPortPrivate) + vid_dec_FreeInputPortPrivate(input); + else + input->nFilledLen = 0; +} diff --git a/src/gallium/state_trackers/omx_bellagio/vid_dec.h b/src/gallium/state_trackers/omx_bellagio/vid_dec.h new file mode 100644 index 00000000000..7a10e750d91 --- /dev/null +++ b/src/gallium/state_trackers/omx_bellagio/vid_dec.h @@ -0,0 +1,148 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Authors: + * Christian König + * + */ + +#ifndef OMX_VID_DEC_H +#define OMX_VID_DEC_H + +#include + +#include +#include +#include + +#include +#include +#include + +#include "pipe/p_video_state.h" +#include "os/os_thread.h" +#include "util/list.h" + +#include "vl/vl_compositor.h" + +#define OMX_VID_DEC_BASE_NAME "OMX.mesa.video_decoder" + +#define OMX_VID_DEC_MPEG2_NAME "OMX.mesa.video_decoder.mpeg2" +#define OMX_VID_DEC_MPEG2_ROLE "video_decoder.mpeg2" + +#define OMX_VID_DEC_AVC_NAME "OMX.mesa.video_decoder.avc" +#define OMX_VID_DEC_AVC_ROLE "video_decoder.avc" + +#define OMX_VID_DEC_HEVC_NAME "OMX.mesa.video_decoder.hevc" +#define OMX_VID_DEC_HEVC_ROLE "video_decoder.hevc" + +#define OMX_VID_DEC_TIMESTAMP_INVALID ((OMX_TICKS) -1) + +struct vl_vlc; + +DERIVEDCLASS(vid_dec_PrivateType, omx_base_filter_PrivateType) +#define vid_dec_PrivateType_FIELDS omx_base_filter_PrivateType_FIELDS \ + enum pipe_video_profile profile; \ + struct vl_screen *screen; \ + struct pipe_context *pipe; \ + struct pipe_video_codec *codec; \ + void (*Decode)(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left); \ + void (*EndFrame)(vid_dec_PrivateType *priv); \ + struct pipe_video_buffer *(*Flush)(vid_dec_PrivateType *priv, OMX_TICKS *timestamp); \ + struct pipe_video_buffer *target, *shadow; \ + union { \ + struct { \ + uint8_t intra_matrix[64]; \ + uint8_t non_intra_matrix[64]; \ + } mpeg12; \ + struct { \ + unsigned nal_ref_idc; \ + bool IdrPicFlag; \ + unsigned idr_pic_id; \ + unsigned pic_order_cnt_lsb; \ + unsigned pic_order_cnt_msb; \ + unsigned delta_pic_order_cnt_bottom; \ + unsigned delta_pic_order_cnt[2]; \ + unsigned prevFrameNumOffset; \ + struct pipe_h264_sps sps[32]; \ + struct pipe_h264_pps pps[256]; \ + struct list_head dpb_list; \ + unsigned dpb_num; \ + } h264; \ + struct { \ + unsigned temporal_id; \ + unsigned level_idc; \ + unsigned pic_width_in_luma_samples; \ + unsigned pic_height_in_luma_samples; \ + bool IdrPicFlag; \ + int slice_prev_poc; \ + void *ref_pic_set_list; \ + void *rps; \ + struct pipe_h265_sps sps[16]; \ + struct pipe_h265_pps pps[64]; \ + struct list_head dpb_list; \ + unsigned dpb_num; \ + } h265; \ + } codec_data; \ + union { \ + struct pipe_picture_desc base; \ + struct pipe_mpeg12_picture_desc mpeg12; \ + struct pipe_h264_picture_desc h264; \ + struct pipe_h265_picture_desc h265; \ + } picture; \ + unsigned num_in_buffers; \ + OMX_BUFFERHEADERTYPE *in_buffers[2]; \ + const void *inputs[2]; \ + unsigned sizes[2]; \ + OMX_TICKS timestamps[2]; \ + OMX_TICKS timestamp; \ + bool first_buf_in_frame; \ + bool frame_finished; \ + bool frame_started; \ + unsigned bytes_left; \ + const void *slice; \ + bool disable_tunnel; \ + struct vl_compositor compositor; \ + struct vl_compositor_state cstate; +ENDCLASS(vid_dec_PrivateType) + +OMX_ERRORTYPE vid_dec_LoaderComponent(stLoaderComponentType *comp); + +/* used by MPEG12 and H264 implementation */ +void vid_dec_NeedTarget(vid_dec_PrivateType *priv); + +/* vid_dec_mpeg12.c */ +void vid_dec_mpeg12_Init(vid_dec_PrivateType *priv); + +/* vid_dec_h264.c */ +void vid_dec_h264_Init(vid_dec_PrivateType *priv); + +/* vid_dec_h265.c */ +void vid_dec_h265_Init(vid_dec_PrivateType *priv); + +#endif diff --git a/src/gallium/state_trackers/omx_bellagio/vid_dec_h264.c b/src/gallium/state_trackers/omx_bellagio/vid_dec_h264.c new file mode 100644 index 00000000000..7ea71c1046b --- /dev/null +++ b/src/gallium/state_trackers/omx_bellagio/vid_dec_h264.c @@ -0,0 +1,1032 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Authors: + * Christian König + * + */ + +#include "pipe/p_video_codec.h" +#include "util/u_memory.h" +#include "util/u_video.h" +#include "vl/vl_rbsp.h" +#include "vl/vl_zscan.h" + +#include "entrypoint.h" +#include "vid_dec.h" + +#define DPB_MAX_SIZE 5 + +struct dpb_list { + struct list_head list; + struct pipe_video_buffer *buffer; + OMX_TICKS timestamp; + int poc; +}; + +static const uint8_t Default_4x4_Intra[16] = { + 6, 13, 20, 28, 13, 20, 28, 32, + 20, 28, 32, 37, 28, 32, 37, 42 +}; + +static const uint8_t Default_4x4_Inter[16] = { + 10, 14, 20, 24, 14, 20, 24, 27, + 20, 24, 27, 30, 24, 27, 30, 34 +}; + +static const uint8_t Default_8x8_Intra[64] = { + 6, 10, 13, 16, 18, 23, 25, 27, + 10, 11, 16, 18, 23, 25, 27, 29, + 13, 16, 18, 23, 25, 27, 29, 31, + 16, 18, 23, 25, 27, 29, 31, 33, + 18, 23, 25, 27, 29, 31, 33, 36, + 23, 25, 27, 29, 31, 33, 36, 38, + 25, 27, 29, 31, 33, 36, 38, 40, + 27, 29, 31, 33, 36, 38, 40, 42 +}; + +static const uint8_t Default_8x8_Inter[64] = { + 9, 13, 15, 17, 19, 21, 22, 24, + 13, 13, 17, 19, 21, 22, 24, 25, + 15, 17, 19, 21, 22, 24, 25, 27, + 17, 19, 21, 22, 24, 25, 27, 28, + 19, 21, 22, 24, 25, 27, 28, 30, + 21, 22, 24, 25, 27, 28, 30, 32, + 22, 24, 25, 27, 28, 30, 32, 33, + 24, 25, 27, 28, 30, 32, 33, 35 +}; + +static void vid_dec_h264_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left); +static void vid_dec_h264_EndFrame(vid_dec_PrivateType *priv); +static struct pipe_video_buffer *vid_dec_h264_Flush(vid_dec_PrivateType *priv, OMX_TICKS *timestamp); + +void vid_dec_h264_Init(vid_dec_PrivateType *priv) +{ + priv->picture.base.profile = PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; + + priv->Decode = vid_dec_h264_Decode; + priv->EndFrame = vid_dec_h264_EndFrame; + priv->Flush = vid_dec_h264_Flush; + + LIST_INITHEAD(&priv->codec_data.h264.dpb_list); + priv->picture.h264.field_order_cnt[0] = priv->picture.h264.field_order_cnt[1] = INT_MAX; + priv->first_buf_in_frame = true; +} + +static void vid_dec_h264_BeginFrame(vid_dec_PrivateType *priv) +{ + //TODO: sane buffer handling + + if (priv->frame_started) + return; + + if (!priv->codec) { + struct pipe_video_codec templat = {}; + omx_base_video_PortType *port; + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; + templat.profile = priv->profile; + templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + templat.max_references = priv->picture.h264.num_ref_frames; + templat.expect_chunked_decode = true; + templat.width = port->sPortParam.format.video.nFrameWidth; + templat.height = port->sPortParam.format.video.nFrameHeight; + templat.level = priv->picture.h264.pps->sps->level_idc; + + priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat); + } + + vid_dec_NeedTarget(priv); + + if (priv->first_buf_in_frame) + priv->timestamp = priv->timestamps[0]; + priv->first_buf_in_frame = false; + + priv->picture.h264.num_ref_frames = priv->picture.h264.pps->sps->max_num_ref_frames; + + priv->picture.h264.slice_count = 0; + priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base); + priv->frame_started = true; +} + +static struct pipe_video_buffer *vid_dec_h264_Flush(vid_dec_PrivateType *priv, + OMX_TICKS *timestamp) +{ + struct dpb_list *entry, *result = NULL; + struct pipe_video_buffer *buf; + + /* search for the lowest poc and break on zeros */ + LIST_FOR_EACH_ENTRY(entry, &priv->codec_data.h264.dpb_list, list) { + + if (result && entry->poc == 0) + break; + + if (!result || entry->poc < result->poc) + result = entry; + } + + if (!result) + return NULL; + + buf = result->buffer; + if (timestamp) + *timestamp = result->timestamp; + + --priv->codec_data.h264.dpb_num; + LIST_DEL(&result->list); + FREE(result); + + return buf; +} + +static void vid_dec_h264_EndFrame(vid_dec_PrivateType *priv) +{ + struct dpb_list *entry; + struct pipe_video_buffer *tmp; + bool top_field_first; + OMX_TICKS timestamp; + + if (!priv->frame_started) + return; + + priv->codec->end_frame(priv->codec, priv->target, &priv->picture.base); + priv->frame_started = false; + + // TODO: implement frame number handling + priv->picture.h264.frame_num_list[0] = priv->picture.h264.frame_num; + priv->picture.h264.field_order_cnt_list[0][0] = priv->picture.h264.frame_num; + priv->picture.h264.field_order_cnt_list[0][1] = priv->picture.h264.frame_num; + + top_field_first = priv->picture.h264.field_order_cnt[0] < priv->picture.h264.field_order_cnt[1]; + + if (priv->picture.h264.field_pic_flag && priv->picture.h264.bottom_field_flag != top_field_first) + return; + + /* add the decoded picture to the dpb list */ + entry = CALLOC_STRUCT(dpb_list); + if (!entry) + return; + + priv->first_buf_in_frame = true; + entry->buffer = priv->target; + entry->timestamp = priv->timestamp; + entry->poc = MIN2(priv->picture.h264.field_order_cnt[0], priv->picture.h264.field_order_cnt[1]); + LIST_ADDTAIL(&entry->list, &priv->codec_data.h264.dpb_list); + ++priv->codec_data.h264.dpb_num; + priv->target = NULL; + priv->picture.h264.field_order_cnt[0] = priv->picture.h264.field_order_cnt[1] = INT_MAX; + + if (priv->codec_data.h264.dpb_num <= DPB_MAX_SIZE) + return; + + tmp = priv->in_buffers[0]->pInputPortPrivate; + priv->in_buffers[0]->pInputPortPrivate = vid_dec_h264_Flush(priv, ×tamp); + priv->in_buffers[0]->nTimeStamp = timestamp; + priv->target = tmp; + priv->frame_finished = priv->in_buffers[0]->pInputPortPrivate != NULL; +} + +static void vui_parameters(struct vl_rbsp *rbsp) +{ + // TODO +} + +static void scaling_list(struct vl_rbsp *rbsp, uint8_t *scalingList, unsigned sizeOfScalingList, + const uint8_t *defaultList, const uint8_t *fallbackList) +{ + unsigned lastScale = 8, nextScale = 8; + const int *list; + unsigned i; + + /* (pic|seq)_scaling_list_present_flag[i] */ + if (!vl_rbsp_u(rbsp, 1)) { + if (fallbackList) + memcpy(scalingList, fallbackList, sizeOfScalingList); + return; + } + + list = (sizeOfScalingList == 16) ? vl_zscan_normal_16 : vl_zscan_normal; + for (i = 0; i < sizeOfScalingList; ++i ) { + + if (nextScale != 0) { + signed delta_scale = vl_rbsp_se(rbsp); + nextScale = (lastScale + delta_scale + 256) % 256; + if (i == 0 && nextScale == 0) { + memcpy(scalingList, defaultList, sizeOfScalingList); + return; + } + } + scalingList[list[i]] = nextScale == 0 ? lastScale : nextScale; + lastScale = scalingList[list[i]]; + } +} + +static struct pipe_h264_sps *seq_parameter_set_id(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) +{ + unsigned id = vl_rbsp_ue(rbsp); + if (id >= ARRAY_SIZE(priv->codec_data.h264.sps)) + return NULL; /* invalid seq_parameter_set_id */ + + return &priv->codec_data.h264.sps[id]; +} + +static void seq_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) +{ + struct pipe_h264_sps *sps; + unsigned profile_idc, level_idc; + unsigned i; + + /* Sequence parameter set */ + profile_idc = vl_rbsp_u(rbsp, 8); + + /* constraint_set0_flag */ + vl_rbsp_u(rbsp, 1); + + /* constraint_set1_flag */ + vl_rbsp_u(rbsp, 1); + + /* constraint_set2_flag */ + vl_rbsp_u(rbsp, 1); + + /* constraint_set3_flag */ + vl_rbsp_u(rbsp, 1); + + /* constraint_set4_flag */ + vl_rbsp_u(rbsp, 1); + + /* constraint_set5_flag */ + vl_rbsp_u(rbsp, 1); + + /* reserved_zero_2bits */ + vl_rbsp_u(rbsp, 2); + + /* level_idc */ + level_idc = vl_rbsp_u(rbsp, 8); + + sps = seq_parameter_set_id(priv, rbsp); + if (!sps) + return; + + memset(sps, 0, sizeof(*sps)); + memset(sps->ScalingList4x4, 16, sizeof(sps->ScalingList4x4)); + memset(sps->ScalingList8x8, 16, sizeof(sps->ScalingList8x8)); + + sps->level_idc = level_idc; + + if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 244 || + profile_idc == 44 || profile_idc == 83 || profile_idc == 86 || profile_idc == 118 || + profile_idc == 128 || profile_idc == 138) { + + sps->chroma_format_idc = vl_rbsp_ue(rbsp); + + if (sps->chroma_format_idc == 3) + sps->separate_colour_plane_flag = vl_rbsp_u(rbsp, 1); + + sps->bit_depth_luma_minus8 = vl_rbsp_ue(rbsp); + + sps->bit_depth_chroma_minus8 = vl_rbsp_ue(rbsp); + + /* qpprime_y_zero_transform_bypass_flag */ + vl_rbsp_u(rbsp, 1); + + sps->seq_scaling_matrix_present_flag = vl_rbsp_u(rbsp, 1); + if (sps->seq_scaling_matrix_present_flag) { + + scaling_list(rbsp, sps->ScalingList4x4[0], 16, Default_4x4_Intra, Default_4x4_Intra); + scaling_list(rbsp, sps->ScalingList4x4[1], 16, Default_4x4_Intra, sps->ScalingList4x4[0]); + scaling_list(rbsp, sps->ScalingList4x4[2], 16, Default_4x4_Intra, sps->ScalingList4x4[1]); + scaling_list(rbsp, sps->ScalingList4x4[3], 16, Default_4x4_Inter, Default_4x4_Inter); + scaling_list(rbsp, sps->ScalingList4x4[4], 16, Default_4x4_Inter, sps->ScalingList4x4[3]); + scaling_list(rbsp, sps->ScalingList4x4[5], 16, Default_4x4_Inter, sps->ScalingList4x4[4]); + + scaling_list(rbsp, sps->ScalingList8x8[0], 64, Default_8x8_Intra, Default_8x8_Intra); + scaling_list(rbsp, sps->ScalingList8x8[1], 64, Default_8x8_Inter, Default_8x8_Inter); + if (sps->chroma_format_idc == 3) { + scaling_list(rbsp, sps->ScalingList8x8[2], 64, Default_8x8_Intra, sps->ScalingList8x8[0]); + scaling_list(rbsp, sps->ScalingList8x8[3], 64, Default_8x8_Inter, sps->ScalingList8x8[1]); + scaling_list(rbsp, sps->ScalingList8x8[4], 64, Default_8x8_Intra, sps->ScalingList8x8[2]); + scaling_list(rbsp, sps->ScalingList8x8[5], 64, Default_8x8_Inter, sps->ScalingList8x8[3]); + } + } + } else if (profile_idc == 183) + sps->chroma_format_idc = 0; + else + sps->chroma_format_idc = 1; + + sps->log2_max_frame_num_minus4 = vl_rbsp_ue(rbsp); + + sps->pic_order_cnt_type = vl_rbsp_ue(rbsp); + + if (sps->pic_order_cnt_type == 0) + sps->log2_max_pic_order_cnt_lsb_minus4 = vl_rbsp_ue(rbsp); + else if (sps->pic_order_cnt_type == 1) { + sps->delta_pic_order_always_zero_flag = vl_rbsp_u(rbsp, 1); + + sps->offset_for_non_ref_pic = vl_rbsp_se(rbsp); + + sps->offset_for_top_to_bottom_field = vl_rbsp_se(rbsp); + + sps->num_ref_frames_in_pic_order_cnt_cycle = vl_rbsp_ue(rbsp); + + for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) + sps->offset_for_ref_frame[i] = vl_rbsp_se(rbsp); + } + + sps->max_num_ref_frames = vl_rbsp_ue(rbsp); + + /* gaps_in_frame_num_value_allowed_flag */ + vl_rbsp_u(rbsp, 1); + + /* pic_width_in_mbs_minus1 */ + vl_rbsp_ue(rbsp); + + /* pic_height_in_map_units_minus1 */ + vl_rbsp_ue(rbsp); + + sps->frame_mbs_only_flag = vl_rbsp_u(rbsp, 1); + if (!sps->frame_mbs_only_flag) + sps->mb_adaptive_frame_field_flag = vl_rbsp_u(rbsp, 1); + + sps->direct_8x8_inference_flag = vl_rbsp_u(rbsp, 1); + + /* frame_cropping_flag */ + if (vl_rbsp_u(rbsp, 1)) { + /* frame_crop_left_offset */ + vl_rbsp_ue(rbsp); + + /* frame_crop_right_offset */ + vl_rbsp_ue(rbsp); + + /* frame_crop_top_offset */ + vl_rbsp_ue(rbsp); + + /* frame_crop_bottom_offset */ + vl_rbsp_ue(rbsp); + } + + /* vui_parameters_present_flag */ + if (vl_rbsp_u(rbsp, 1)) + vui_parameters(rbsp); +} + +static struct pipe_h264_pps *pic_parameter_set_id(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) +{ + unsigned id = vl_rbsp_ue(rbsp); + if (id >= ARRAY_SIZE(priv->codec_data.h264.pps)) + return NULL; /* invalid pic_parameter_set_id */ + + return &priv->codec_data.h264.pps[id]; +} + +static void picture_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) +{ + struct pipe_h264_sps *sps; + struct pipe_h264_pps *pps; + unsigned i; + + pps = pic_parameter_set_id(priv, rbsp); + if (!pps) + return; + + memset(pps, 0, sizeof(*pps)); + + sps = pps->sps = seq_parameter_set_id(priv, rbsp); + if (!sps) + return; + + memcpy(pps->ScalingList4x4, sps->ScalingList4x4, sizeof(pps->ScalingList4x4)); + memcpy(pps->ScalingList8x8, sps->ScalingList8x8, sizeof(pps->ScalingList8x8)); + + pps->entropy_coding_mode_flag = vl_rbsp_u(rbsp, 1); + + pps->bottom_field_pic_order_in_frame_present_flag = vl_rbsp_u(rbsp, 1); + + pps->num_slice_groups_minus1 = vl_rbsp_ue(rbsp); + if (pps->num_slice_groups_minus1 > 0) { + pps->slice_group_map_type = vl_rbsp_ue(rbsp); + + if (pps->slice_group_map_type == 0) { + + for (i = 0; i <= pps->num_slice_groups_minus1; ++i) + /* run_length_minus1[i] */ + vl_rbsp_ue(rbsp); + + } else if (pps->slice_group_map_type == 2) { + + for (i = 0; i <= pps->num_slice_groups_minus1; ++i) { + /* top_left[i] */ + vl_rbsp_ue(rbsp); + + /* bottom_right[i] */ + vl_rbsp_ue(rbsp); + } + + } else if (pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5) { + + /* slice_group_change_direction_flag */ + vl_rbsp_u(rbsp, 1); + + pps->slice_group_change_rate_minus1 = vl_rbsp_ue(rbsp); + + } else if (pps->slice_group_map_type == 6) { + + unsigned pic_size_in_map_units_minus1; + + pic_size_in_map_units_minus1 = vl_rbsp_ue(rbsp); + + for (i = 0; i <= pic_size_in_map_units_minus1; ++i) + /* slice_group_id[i] */ + vl_rbsp_u(rbsp, log2(pps->num_slice_groups_minus1 + 1)); + } + } + + pps->num_ref_idx_l0_default_active_minus1 = vl_rbsp_ue(rbsp); + + pps->num_ref_idx_l1_default_active_minus1 = vl_rbsp_ue(rbsp); + + pps->weighted_pred_flag = vl_rbsp_u(rbsp, 1); + + pps->weighted_bipred_idc = vl_rbsp_u(rbsp, 2); + + pps->pic_init_qp_minus26 = vl_rbsp_se(rbsp); + + /* pic_init_qs_minus26 */ + vl_rbsp_se(rbsp); + + pps->chroma_qp_index_offset = vl_rbsp_se(rbsp); + + pps->deblocking_filter_control_present_flag = vl_rbsp_u(rbsp, 1); + + pps->constrained_intra_pred_flag = vl_rbsp_u(rbsp, 1); + + pps->redundant_pic_cnt_present_flag = vl_rbsp_u(rbsp, 1); + + if (vl_rbsp_more_data(rbsp)) { + pps->transform_8x8_mode_flag = vl_rbsp_u(rbsp, 1); + + /* pic_scaling_matrix_present_flag */ + if (vl_rbsp_u(rbsp, 1)) { + + scaling_list(rbsp, pps->ScalingList4x4[0], 16, Default_4x4_Intra, + sps->seq_scaling_matrix_present_flag ? NULL : Default_4x4_Intra); + scaling_list(rbsp, pps->ScalingList4x4[1], 16, Default_4x4_Intra, pps->ScalingList4x4[0]); + scaling_list(rbsp, pps->ScalingList4x4[2], 16, Default_4x4_Intra, pps->ScalingList4x4[1]); + scaling_list(rbsp, pps->ScalingList4x4[3], 16, Default_4x4_Inter, + sps->seq_scaling_matrix_present_flag ? NULL : Default_4x4_Inter); + scaling_list(rbsp, pps->ScalingList4x4[4], 16, Default_4x4_Inter, pps->ScalingList4x4[3]); + scaling_list(rbsp, pps->ScalingList4x4[5], 16, Default_4x4_Inter, pps->ScalingList4x4[4]); + + if (pps->transform_8x8_mode_flag) { + scaling_list(rbsp, pps->ScalingList8x8[0], 64, Default_8x8_Intra, + sps->seq_scaling_matrix_present_flag ? NULL : Default_8x8_Intra); + scaling_list(rbsp, pps->ScalingList8x8[1], 64, Default_8x8_Inter, + sps->seq_scaling_matrix_present_flag ? NULL : Default_8x8_Inter); + if (sps->chroma_format_idc == 3) { + scaling_list(rbsp, pps->ScalingList8x8[2], 64, Default_8x8_Intra, pps->ScalingList8x8[0]); + scaling_list(rbsp, pps->ScalingList8x8[3], 64, Default_8x8_Inter, pps->ScalingList8x8[1]); + scaling_list(rbsp, pps->ScalingList8x8[4], 64, Default_8x8_Intra, pps->ScalingList8x8[2]); + scaling_list(rbsp, pps->ScalingList8x8[5], 64, Default_8x8_Inter, pps->ScalingList8x8[3]); + } + } + } + + pps->second_chroma_qp_index_offset = vl_rbsp_se(rbsp); + } +} + +static void ref_pic_list_mvc_modification(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) +{ + // TODO + assert(0); +} + +static void ref_pic_list_modification(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, + enum pipe_h264_slice_type slice_type) +{ + unsigned modification_of_pic_nums_idc; + + if (slice_type != 2 && slice_type != 4) { + /* ref_pic_list_modification_flag_l0 */ + if (vl_rbsp_u(rbsp, 1)) { + do { + modification_of_pic_nums_idc = vl_rbsp_ue(rbsp); + if (modification_of_pic_nums_idc == 0 || + modification_of_pic_nums_idc == 1) + /* abs_diff_pic_num_minus1 */ + vl_rbsp_ue(rbsp); + else if (modification_of_pic_nums_idc == 2) + /* long_term_pic_num */ + vl_rbsp_ue(rbsp); + } while (modification_of_pic_nums_idc != 3); + } + } + + if (slice_type == 1) { + /* ref_pic_list_modification_flag_l1 */ + if (vl_rbsp_u(rbsp, 1)) { + do { + modification_of_pic_nums_idc = vl_rbsp_ue(rbsp); + if (modification_of_pic_nums_idc == 0 || + modification_of_pic_nums_idc == 1) + /* abs_diff_pic_num_minus1 */ + vl_rbsp_ue(rbsp); + else if (modification_of_pic_nums_idc == 2) + /* long_term_pic_num */ + vl_rbsp_ue(rbsp); + } while (modification_of_pic_nums_idc != 3); + } + } +} + +static void pred_weight_table(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, + struct pipe_h264_sps *sps, enum pipe_h264_slice_type slice_type) +{ + unsigned ChromaArrayType = sps->separate_colour_plane_flag ? 0 : sps->chroma_format_idc; + unsigned i, j; + + /* luma_log2_weight_denom */ + vl_rbsp_ue(rbsp); + + if (ChromaArrayType != 0) + /* chroma_log2_weight_denom */ + vl_rbsp_ue(rbsp); + + for (i = 0; i <= priv->picture.h264.num_ref_idx_l0_active_minus1; ++i) { + /* luma_weight_l0_flag */ + if (vl_rbsp_u(rbsp, 1)) { + /* luma_weight_l0[i] */ + vl_rbsp_se(rbsp); + /* luma_offset_l0[i] */ + vl_rbsp_se(rbsp); + } + if (ChromaArrayType != 0) { + /* chroma_weight_l0_flag */ + if (vl_rbsp_u(rbsp, 1)) { + for (j = 0; j < 2; ++j) { + /* chroma_weight_l0[i][j] */ + vl_rbsp_se(rbsp); + /* chroma_offset_l0[i][j] */ + vl_rbsp_se(rbsp); + } + } + } + } + + if (slice_type == 1) { + for (i = 0; i <= priv->picture.h264.num_ref_idx_l1_active_minus1; ++i) { + /* luma_weight_l1_flag */ + if (vl_rbsp_u(rbsp, 1)) { + /* luma_weight_l1[i] */ + vl_rbsp_se(rbsp); + /* luma_offset_l1[i] */ + vl_rbsp_se(rbsp); + } + if (ChromaArrayType != 0) { + /* chroma_weight_l1_flag */ + if (vl_rbsp_u(rbsp, 1)) { + for (j = 0; j < 2; ++j) { + /* chroma_weight_l1[i][j] */ + vl_rbsp_se(rbsp); + /* chroma_offset_l1[i][j] */ + vl_rbsp_se(rbsp); + } + } + } + } + } +} + +static void dec_ref_pic_marking(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, + bool IdrPicFlag) +{ + unsigned memory_management_control_operation; + + if (IdrPicFlag) { + /* no_output_of_prior_pics_flag */ + vl_rbsp_u(rbsp, 1); + /* long_term_reference_flag */ + vl_rbsp_u(rbsp, 1); + } else { + /* adaptive_ref_pic_marking_mode_flag */ + if (vl_rbsp_u(rbsp, 1)) { + do { + memory_management_control_operation = vl_rbsp_ue(rbsp); + + if (memory_management_control_operation == 1 || + memory_management_control_operation == 3) + /* difference_of_pic_nums_minus1 */ + vl_rbsp_ue(rbsp); + + if (memory_management_control_operation == 2) + /* long_term_pic_num */ + vl_rbsp_ue(rbsp); + + if (memory_management_control_operation == 3 || + memory_management_control_operation == 6) + /* long_term_frame_idx */ + vl_rbsp_ue(rbsp); + + if (memory_management_control_operation == 4) + /* max_long_term_frame_idx_plus1 */ + vl_rbsp_ue(rbsp); + } while (memory_management_control_operation != 0); + } + } +} + +static void slice_header(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, + unsigned nal_ref_idc, unsigned nal_unit_type) +{ + enum pipe_h264_slice_type slice_type; + struct pipe_h264_pps *pps; + struct pipe_h264_sps *sps; + unsigned frame_num, prevFrameNum; + bool IdrPicFlag = nal_unit_type == 5; + + if (IdrPicFlag != priv->codec_data.h264.IdrPicFlag) + vid_dec_h264_EndFrame(priv); + + priv->codec_data.h264.IdrPicFlag = IdrPicFlag; + + /* first_mb_in_slice */ + vl_rbsp_ue(rbsp); + + slice_type = vl_rbsp_ue(rbsp) % 5; + + pps = pic_parameter_set_id(priv, rbsp); + if (!pps) + return; + + sps = pps->sps; + if (!sps) + return; + + if (pps != priv->picture.h264.pps) + vid_dec_h264_EndFrame(priv); + + priv->picture.h264.pps = pps; + + if (sps->separate_colour_plane_flag == 1 ) + /* colour_plane_id */ + vl_rbsp_u(rbsp, 2); + + frame_num = vl_rbsp_u(rbsp, sps->log2_max_frame_num_minus4 + 4); + + if (frame_num != priv->picture.h264.frame_num) + vid_dec_h264_EndFrame(priv); + + prevFrameNum = priv->picture.h264.frame_num; + priv->picture.h264.frame_num = frame_num; + + priv->picture.h264.field_pic_flag = 0; + priv->picture.h264.bottom_field_flag = 0; + + if (!sps->frame_mbs_only_flag) { + unsigned field_pic_flag = vl_rbsp_u(rbsp, 1); + + if (!field_pic_flag && field_pic_flag != priv->picture.h264.field_pic_flag) + vid_dec_h264_EndFrame(priv); + + priv->picture.h264.field_pic_flag = field_pic_flag; + + if (priv->picture.h264.field_pic_flag) { + unsigned bottom_field_flag = vl_rbsp_u(rbsp, 1); + + if (bottom_field_flag != priv->picture.h264.bottom_field_flag) + vid_dec_h264_EndFrame(priv); + + priv->picture.h264.bottom_field_flag = bottom_field_flag; + } + } + + if (IdrPicFlag) { + unsigned idr_pic_id = vl_rbsp_ue(rbsp); + + if (idr_pic_id != priv->codec_data.h264.idr_pic_id) + vid_dec_h264_EndFrame(priv); + + priv->codec_data.h264.idr_pic_id = idr_pic_id; + } + + if (sps->pic_order_cnt_type == 0) { + unsigned log2_max_pic_order_cnt_lsb = sps->log2_max_pic_order_cnt_lsb_minus4 + 4; + unsigned max_pic_order_cnt_lsb = 1 << log2_max_pic_order_cnt_lsb; + int pic_order_cnt_lsb = vl_rbsp_u(rbsp, log2_max_pic_order_cnt_lsb); + int pic_order_cnt_msb; + + if (pic_order_cnt_lsb != priv->codec_data.h264.pic_order_cnt_lsb) + vid_dec_h264_EndFrame(priv); + + if (IdrPicFlag) { + priv->codec_data.h264.pic_order_cnt_msb = 0; + priv->codec_data.h264.pic_order_cnt_lsb = 0; + } + + if ((pic_order_cnt_lsb < priv->codec_data.h264.pic_order_cnt_lsb) && + (priv->codec_data.h264.pic_order_cnt_lsb - pic_order_cnt_lsb) >= (max_pic_order_cnt_lsb / 2)) + pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb + max_pic_order_cnt_lsb; + + else if ((pic_order_cnt_lsb > priv->codec_data.h264.pic_order_cnt_lsb) && + (pic_order_cnt_lsb - priv->codec_data.h264.pic_order_cnt_lsb) > (max_pic_order_cnt_lsb / 2)) + pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb - max_pic_order_cnt_lsb; + + else + pic_order_cnt_msb = priv->codec_data.h264.pic_order_cnt_msb; + + priv->codec_data.h264.pic_order_cnt_msb = pic_order_cnt_msb; + priv->codec_data.h264.pic_order_cnt_lsb = pic_order_cnt_lsb; + + if (pps->bottom_field_pic_order_in_frame_present_flag && !priv->picture.h264.field_pic_flag) { + unsigned delta_pic_order_cnt_bottom = vl_rbsp_se(rbsp); + + if (delta_pic_order_cnt_bottom != priv->codec_data.h264.delta_pic_order_cnt_bottom) + vid_dec_h264_EndFrame(priv); + + priv->codec_data.h264.delta_pic_order_cnt_bottom = delta_pic_order_cnt_bottom; + } + + if (!priv->picture.h264.field_pic_flag) { + priv->picture.h264.field_order_cnt[0] = pic_order_cnt_msb + pic_order_cnt_lsb; + priv->picture.h264.field_order_cnt[1] = priv->picture.h264.field_order_cnt [0] + + priv->codec_data.h264.delta_pic_order_cnt_bottom; + } else if (!priv->picture.h264.bottom_field_flag) + priv->picture.h264.field_order_cnt[0] = pic_order_cnt_msb + pic_order_cnt_lsb; + else + priv->picture.h264.field_order_cnt[1] = pic_order_cnt_msb + pic_order_cnt_lsb; + + } else if (sps->pic_order_cnt_type == 1) { + unsigned MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4); + unsigned FrameNumOffset, absFrameNum, expectedPicOrderCnt; + + if (!sps->delta_pic_order_always_zero_flag) { + unsigned delta_pic_order_cnt[2]; + + delta_pic_order_cnt[0] = vl_rbsp_se(rbsp); + + if (delta_pic_order_cnt[0] != priv->codec_data.h264.delta_pic_order_cnt[0]) + vid_dec_h264_EndFrame(priv); + + priv->codec_data.h264.delta_pic_order_cnt[0] = delta_pic_order_cnt[0]; + + if (pps->bottom_field_pic_order_in_frame_present_flag && !priv->picture.h264.field_pic_flag) { + delta_pic_order_cnt[1] = vl_rbsp_se(rbsp); + + if (delta_pic_order_cnt[1] != priv->codec_data.h264.delta_pic_order_cnt[1]) + vid_dec_h264_EndFrame(priv); + + priv->codec_data.h264.delta_pic_order_cnt[1] = delta_pic_order_cnt[1]; + } + } + + if (IdrPicFlag) + FrameNumOffset = 0; + else if (prevFrameNum > frame_num) + FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset + MaxFrameNum; + else + FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset; + + priv->codec_data.h264.prevFrameNumOffset = FrameNumOffset; + + if (sps->num_ref_frames_in_pic_order_cnt_cycle != 0) + absFrameNum = FrameNumOffset + frame_num; + else + absFrameNum = 0; + + if (nal_ref_idc == 0 && absFrameNum > 0) + absFrameNum = absFrameNum - 1; + + if (absFrameNum > 0) { + unsigned picOrderCntCycleCnt = (absFrameNum - 1) / sps->num_ref_frames_in_pic_order_cnt_cycle; + unsigned frameNumInPicOrderCntCycle = (absFrameNum - 1) % sps->num_ref_frames_in_pic_order_cnt_cycle; + signed ExpectedDeltaPerPicOrderCntCycle = 0; + unsigned i; + + for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; ++i) + ExpectedDeltaPerPicOrderCntCycle += sps->offset_for_ref_frame[i]; + + expectedPicOrderCnt = picOrderCntCycleCnt * ExpectedDeltaPerPicOrderCntCycle; + for (i = 0; i <= frameNumInPicOrderCntCycle; ++i) + expectedPicOrderCnt += sps->offset_for_ref_frame[i]; + + } else + expectedPicOrderCnt = 0; + + if (nal_ref_idc == 0) + expectedPicOrderCnt += sps->offset_for_non_ref_pic; + + if (!priv->picture.h264.field_pic_flag) { + priv->picture.h264.field_order_cnt[0] = expectedPicOrderCnt + priv->codec_data.h264.delta_pic_order_cnt[0]; + priv->picture.h264.field_order_cnt[1] = priv->picture.h264.field_order_cnt[0] + + sps->offset_for_top_to_bottom_field + priv->codec_data.h264.delta_pic_order_cnt[1]; + + } else if (!priv->picture.h264.bottom_field_flag) + priv->picture.h264.field_order_cnt[0] = expectedPicOrderCnt + priv->codec_data.h264.delta_pic_order_cnt[0]; + else + priv->picture.h264.field_order_cnt[1] = expectedPicOrderCnt + sps->offset_for_top_to_bottom_field + + priv->codec_data.h264.delta_pic_order_cnt[0]; + + } else if (sps->pic_order_cnt_type == 2) { + unsigned MaxFrameNum = 1 << (sps->log2_max_frame_num_minus4 + 4); + unsigned FrameNumOffset, tempPicOrderCnt; + + if (IdrPicFlag) + FrameNumOffset = 0; + else if (prevFrameNum > frame_num) + FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset + MaxFrameNum; + else + FrameNumOffset = priv->codec_data.h264.prevFrameNumOffset; + + priv->codec_data.h264.prevFrameNumOffset = FrameNumOffset; + + if (IdrPicFlag) + tempPicOrderCnt = 0; + else if (nal_ref_idc == 0) + tempPicOrderCnt = 2 * (FrameNumOffset + frame_num) - 1; + else + tempPicOrderCnt = 2 * (FrameNumOffset + frame_num); + + if (!priv->picture.h264.field_pic_flag) { + priv->picture.h264.field_order_cnt[0] = tempPicOrderCnt; + priv->picture.h264.field_order_cnt[1] = tempPicOrderCnt; + + } else if (!priv->picture.h264.bottom_field_flag) + priv->picture.h264.field_order_cnt[0] = tempPicOrderCnt; + else + priv->picture.h264.field_order_cnt[1] = tempPicOrderCnt; + } + + if (pps->redundant_pic_cnt_present_flag) + /* redundant_pic_cnt */ + vl_rbsp_ue(rbsp); + + if (slice_type == PIPE_H264_SLICE_TYPE_B) + /* direct_spatial_mv_pred_flag */ + vl_rbsp_u(rbsp, 1); + + priv->picture.h264.num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_default_active_minus1; + priv->picture.h264.num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_default_active_minus1; + + if (slice_type == PIPE_H264_SLICE_TYPE_P || + slice_type == PIPE_H264_SLICE_TYPE_SP || + slice_type == PIPE_H264_SLICE_TYPE_B) { + + /* num_ref_idx_active_override_flag */ + if (vl_rbsp_u(rbsp, 1)) { + priv->picture.h264.num_ref_idx_l0_active_minus1 = vl_rbsp_ue(rbsp); + + if (slice_type == PIPE_H264_SLICE_TYPE_B) + priv->picture.h264.num_ref_idx_l1_active_minus1 = vl_rbsp_ue(rbsp); + } + } + + if (nal_unit_type == 20 || nal_unit_type == 21) + ref_pic_list_mvc_modification(priv, rbsp); + else + ref_pic_list_modification(priv, rbsp, slice_type); + + if ((pps->weighted_pred_flag && (slice_type == PIPE_H264_SLICE_TYPE_P || slice_type == PIPE_H264_SLICE_TYPE_SP)) || + (pps->weighted_bipred_idc == 1 && slice_type == PIPE_H264_SLICE_TYPE_B)) + pred_weight_table(priv, rbsp, sps, slice_type); + + if (nal_ref_idc != 0) + dec_ref_pic_marking(priv, rbsp, IdrPicFlag); + + if (pps->entropy_coding_mode_flag && slice_type != PIPE_H264_SLICE_TYPE_I && slice_type != PIPE_H264_SLICE_TYPE_SI) + /* cabac_init_idc */ + vl_rbsp_ue(rbsp); + + /* slice_qp_delta */ + vl_rbsp_se(rbsp); + + if (slice_type == PIPE_H264_SLICE_TYPE_SP || slice_type == PIPE_H264_SLICE_TYPE_SI) { + if (slice_type == PIPE_H264_SLICE_TYPE_SP) + /* sp_for_switch_flag */ + vl_rbsp_u(rbsp, 1); + + /*slice_qs_delta */ + vl_rbsp_se(rbsp); + } + + if (pps->deblocking_filter_control_present_flag) { + unsigned disable_deblocking_filter_idc = vl_rbsp_ue(rbsp); + + if (disable_deblocking_filter_idc != 1) { + /* slice_alpha_c0_offset_div2 */ + vl_rbsp_se(rbsp); + + /* slice_beta_offset_div2 */ + vl_rbsp_se(rbsp); + } + } + + if (pps->num_slice_groups_minus1 > 0 && pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5) + /* slice_group_change_cycle */ + vl_rbsp_u(rbsp, 2); +} + +static void vid_dec_h264_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left) +{ + unsigned nal_ref_idc, nal_unit_type; + + if (!vl_vlc_search_byte(vlc, vl_vlc_bits_left(vlc) - min_bits_left, 0x00)) + return; + + if (vl_vlc_peekbits(vlc, 24) != 0x000001) { + vl_vlc_eatbits(vlc, 8); + return; + } + + if (priv->slice) { + unsigned bytes = priv->bytes_left - (vl_vlc_bits_left(vlc) / 8); + ++priv->picture.h264.slice_count; + priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, + 1, &priv->slice, &bytes); + priv->slice = NULL; + } + + vl_vlc_eatbits(vlc, 24); + + /* forbidden_zero_bit */ + vl_vlc_eatbits(vlc, 1); + + nal_ref_idc = vl_vlc_get_uimsbf(vlc, 2); + + if (nal_ref_idc != priv->codec_data.h264.nal_ref_idc && + (nal_ref_idc * priv->codec_data.h264.nal_ref_idc) == 0) + vid_dec_h264_EndFrame(priv); + + priv->codec_data.h264.nal_ref_idc = nal_ref_idc; + + nal_unit_type = vl_vlc_get_uimsbf(vlc, 5); + + if (nal_unit_type != 1 && nal_unit_type != 5) + vid_dec_h264_EndFrame(priv); + + if (nal_unit_type == 7) { + struct vl_rbsp rbsp; + vl_rbsp_init(&rbsp, vlc, ~0); + seq_parameter_set(priv, &rbsp); + + } else if (nal_unit_type == 8) { + struct vl_rbsp rbsp; + vl_rbsp_init(&rbsp, vlc, ~0); + picture_parameter_set(priv, &rbsp); + + } else if (nal_unit_type == 1 || nal_unit_type == 5) { + /* Coded slice of a non-IDR or IDR picture */ + unsigned bits = vl_vlc_valid_bits(vlc); + unsigned bytes = bits / 8 + 4; + struct vl_rbsp rbsp; + uint8_t buf[8]; + const void *ptr = buf; + unsigned i; + + buf[0] = 0x0; + buf[1] = 0x0; + buf[2] = 0x1; + buf[3] = (nal_ref_idc << 5) | nal_unit_type; + for (i = 4; i < bytes; ++i) + buf[i] = vl_vlc_peekbits(vlc, bits) >> ((bytes - i - 1) * 8); + + priv->bytes_left = (vl_vlc_bits_left(vlc) - bits) / 8; + priv->slice = vlc->data; + + vl_rbsp_init(&rbsp, vlc, 128); + slice_header(priv, &rbsp, nal_ref_idc, nal_unit_type); + + vid_dec_h264_BeginFrame(priv); + + ++priv->picture.h264.slice_count; + priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, + 1, &ptr, &bytes); + } + + /* resync to byte boundary */ + vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8); +} diff --git a/src/gallium/state_trackers/omx_bellagio/vid_dec_h265.c b/src/gallium/state_trackers/omx_bellagio/vid_dec_h265.c new file mode 100644 index 00000000000..3242dbe11c8 --- /dev/null +++ b/src/gallium/state_trackers/omx_bellagio/vid_dec_h265.c @@ -0,0 +1,1013 @@ +/************************************************************************** + * + * Copyright 2016 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "pipe/p_video_codec.h" +#include "util/u_memory.h" +#include "util/u_video.h" +#include "vl/vl_rbsp.h" + +#include "entrypoint.h" +#include "vid_dec.h" + +#define DPB_MAX_SIZE 32 +#define MAX_NUM_REF_PICS 16 + +enum { + NAL_UNIT_TYPE_TRAIL_N = 0, + NAL_UNIT_TYPE_TRAIL_R = 1, + NAL_UNIT_TYPE_TSA_N = 2, + NAL_UNIT_TYPE_TSA_R = 3, + NAL_UNIT_TYPE_STSA_N = 4, + NAL_UNIT_TYPE_STSA_R = 5, + NAL_UNIT_TYPE_RADL_N = 6, + NAL_UNIT_TYPE_RADL_R = 7, + NAL_UNIT_TYPE_RASL_N = 8, + NAL_UNIT_TYPE_RASL_R = 9, + NAL_UNIT_TYPE_BLA_W_LP = 16, + NAL_UNIT_TYPE_BLA_W_RADL = 17, + NAL_UNIT_TYPE_BLA_N_LP = 18, + NAL_UNIT_TYPE_IDR_W_RADL = 19, + NAL_UNIT_TYPE_IDR_N_LP = 20, + NAL_UNIT_TYPE_CRA = 21, + NAL_UNIT_TYPE_SPS = 33, + NAL_UNIT_TYPE_PPS = 34, +}; + +static const uint8_t Default_8x8_Intra[64] = { + 16, 16, 16, 16, 17, 18, 21, 24, + 16, 16, 16, 16, 17, 19, 22, 25, + 16, 16, 17, 18, 20, 22, 25, 29, + 16, 16, 18, 21, 24, 27, 31, 36, + 17, 17, 20, 24, 30, 35, 41, 47, + 18, 19, 22, 27, 35, 44, 54, 65, + 21, 22, 25, 31, 41, 54, 70, 88, + 24, 25, 29, 36, 47, 65, 88, 115 +}; + +static const uint8_t Default_8x8_Inter[64] = { + 16, 16, 16, 16, 17, 18, 20, 24, + 16, 16, 16, 17, 18, 20, 24, 25, + 16, 16, 17, 18, 20, 24, 25, 28, + 16, 17, 18, 20, 24, 25, 28, 33, + 17, 18, 20, 24, 25, 28, 33, 41, + 18, 20, 24, 25, 28, 33, 41, 54, + 20, 24, 25, 28, 33, 41, 54, 71, + 24, 25, 28, 33, 41, 54, 71, 91 +}; + +struct dpb_list { + struct list_head list; + struct pipe_video_buffer *buffer; + OMX_TICKS timestamp; + unsigned poc; +}; + +struct ref_pic_set { + unsigned num_pics; + unsigned num_neg_pics; + unsigned num_pos_pics; + unsigned num_delta_poc; + int delta_poc[MAX_NUM_REF_PICS]; + bool used[MAX_NUM_REF_PICS]; +}; + +static bool is_idr_picture(unsigned nal_unit_type) +{ + return (nal_unit_type == NAL_UNIT_TYPE_IDR_W_RADL || + nal_unit_type == NAL_UNIT_TYPE_IDR_N_LP); +} + +/* broken link access picture */ +static bool is_bla_picture(unsigned nal_unit_type) +{ + return (nal_unit_type == NAL_UNIT_TYPE_BLA_W_LP || + nal_unit_type == NAL_UNIT_TYPE_BLA_W_RADL || + nal_unit_type == NAL_UNIT_TYPE_BLA_N_LP); +} + +/* random access point picture */ +static bool is_rap_picture(unsigned nal_unit_type) +{ + return (nal_unit_type >= NAL_UNIT_TYPE_BLA_W_LP && + nal_unit_type <= NAL_UNIT_TYPE_CRA); +} + +static bool is_slice_picture(unsigned nal_unit_type) +{ + return (nal_unit_type <= NAL_UNIT_TYPE_RASL_R || + is_rap_picture(nal_unit_type)); +} + +static void set_poc(vid_dec_PrivateType *priv, + unsigned nal_unit_type, int i) +{ + priv->picture.h265.CurrPicOrderCntVal = i; + + if (priv->codec_data.h265.temporal_id == 0 && + (nal_unit_type == NAL_UNIT_TYPE_TRAIL_R || + nal_unit_type == NAL_UNIT_TYPE_TSA_R || + nal_unit_type == NAL_UNIT_TYPE_STSA_R || + is_rap_picture(nal_unit_type))) + priv->codec_data.h265.slice_prev_poc = i; +} + +static unsigned get_poc(vid_dec_PrivateType *priv) +{ + return priv->picture.h265.CurrPicOrderCntVal; +} + +static void profile_tier(struct vl_rbsp *rbsp) +{ + int i; + + /* general_profile_space */ + vl_rbsp_u(rbsp, 2); + + /* general_tier_flag */ + vl_rbsp_u(rbsp, 1); + + /* general_profile_idc */ + vl_rbsp_u(rbsp, 5); + + /* general_profile_compatibility_flag */ + for(i = 0; i < 32; ++i) + vl_rbsp_u(rbsp, 1); + + /* general_progressive_source_flag */ + vl_rbsp_u(rbsp, 1); + + /* general_interlaced_source_flag */ + vl_rbsp_u(rbsp, 1); + + /* general_non_packed_constraint_flag */ + vl_rbsp_u(rbsp, 1); + + /* general_frame_only_constraint_flag */ + vl_rbsp_u(rbsp, 1); + + /* general_reserved_zero_44bits */ + vl_rbsp_u(rbsp, 16); + vl_rbsp_u(rbsp, 16); + vl_rbsp_u(rbsp, 12); +} + +static unsigned profile_tier_level(struct vl_rbsp *rbsp, + int max_sublayers_minus1) +{ + bool sub_layer_profile_present_flag[6]; + bool sub_layer_level_present_flag[6]; + unsigned level_idc; + int i; + + profile_tier(rbsp); + + /* general_level_idc */ + level_idc = vl_rbsp_u(rbsp, 8); + + for (i = 0; i < max_sublayers_minus1; ++i) { + sub_layer_profile_present_flag[i] = vl_rbsp_u(rbsp, 1); + sub_layer_level_present_flag[i] = vl_rbsp_u(rbsp, 1); + } + + if (max_sublayers_minus1 > 0) + for (i = max_sublayers_minus1; i < 8; ++i) + /* reserved_zero_2bits */ + vl_rbsp_u(rbsp, 2); + + for (i = 0; i < max_sublayers_minus1; ++i) { + if (sub_layer_profile_present_flag[i]) + profile_tier(rbsp); + + if (sub_layer_level_present_flag[i]) + /* sub_layer_level_idc */ + vl_rbsp_u(rbsp, 8); + } + + return level_idc; +} + +static void scaling_list_data(vid_dec_PrivateType *priv, + struct vl_rbsp *rbsp, struct pipe_h265_sps *sps) +{ + unsigned size_id, matrix_id; + unsigned scaling_list_len[4] = { 16, 64, 64, 64 }; + uint8_t scaling_list4x4[6][64] = { }; + int i; + + uint8_t (*scaling_list_data[4])[6][64] = { + (uint8_t (*)[6][64])scaling_list4x4, + (uint8_t (*)[6][64])sps->ScalingList8x8, + (uint8_t (*)[6][64])sps->ScalingList16x16, + (uint8_t (*)[6][64])sps->ScalingList32x32 + }; + uint8_t (*scaling_list_dc_coeff[2])[6] = { + (uint8_t (*)[6])sps->ScalingListDCCoeff16x16, + (uint8_t (*)[6])sps->ScalingListDCCoeff32x32 + }; + + for (size_id = 0; size_id < 4; ++size_id) { + + for (matrix_id = 0; matrix_id < ((size_id == 3) ? 2 : 6); ++matrix_id) { + bool scaling_list_pred_mode_flag = vl_rbsp_u(rbsp, 1); + + if (!scaling_list_pred_mode_flag) { + /* scaling_list_pred_matrix_id_delta */; + unsigned matrix_id_with_delta = matrix_id - vl_rbsp_ue(rbsp); + + if (matrix_id != matrix_id_with_delta) { + memcpy((*scaling_list_data[size_id])[matrix_id], + (*scaling_list_data[size_id])[matrix_id_with_delta], + scaling_list_len[size_id]); + if (size_id > 1) + (*scaling_list_dc_coeff[size_id - 2])[matrix_id] = + (*scaling_list_dc_coeff[size_id - 2])[matrix_id_with_delta]; + } else { + const uint8_t *d; + + if (size_id == 0) + memset((*scaling_list_data[0])[matrix_id], 16, 16); + else { + if (size_id < 3) + d = (matrix_id < 3) ? Default_8x8_Intra : Default_8x8_Inter; + else + d = (matrix_id < 1) ? Default_8x8_Intra : Default_8x8_Inter; + memcpy((*scaling_list_data[size_id])[matrix_id], d, + scaling_list_len[size_id]); + } + if (size_id > 1) + (*scaling_list_dc_coeff[size_id - 2])[matrix_id] = 16; + } + } else { + int next_coef = 8; + int coef_num = MIN2(64, (1 << (4 + (size_id << 1)))); + + if (size_id > 1) { + /* scaling_list_dc_coef_minus8 */ + next_coef = vl_rbsp_se(rbsp) + 8; + (*scaling_list_dc_coeff[size_id - 2])[matrix_id] = next_coef; + } + + for (i = 0; i < coef_num; ++i) { + /* scaling_list_delta_coef */ + next_coef = (next_coef + vl_rbsp_se(rbsp) + 256) % 256; + (*scaling_list_data[size_id])[matrix_id][i] = next_coef; + } + } + } + } + + for (i = 0; i < 6; ++i) + memcpy(sps->ScalingList4x4[i], scaling_list4x4[i], 16); + + return; +} + +static void st_ref_pic_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, + struct ref_pic_set *rps, struct pipe_h265_sps *sps, + unsigned idx) +{ + bool inter_rps_pred_flag; + unsigned delta_idx_minus1; + int delta_poc; + int i; + + inter_rps_pred_flag = (idx != 0) ? (vl_rbsp_u(rbsp, 1)) : false; + + if (inter_rps_pred_flag) { + struct ref_pic_set *ref_rps; + unsigned sign, abs; + int delta_rps; + bool used; + int j; + + if (idx == sps->num_short_term_ref_pic_sets) + delta_idx_minus1 = vl_rbsp_ue(rbsp); + else + delta_idx_minus1 = 0; + + ref_rps = (struct ref_pic_set *) + priv->codec_data.h265.ref_pic_set_list + idx - (delta_idx_minus1 + 1); + + /* delta_rps_sign */ + sign = vl_rbsp_u(rbsp, 1); + /* abs_delta_rps_minus1 */ + abs = vl_rbsp_ue(rbsp); + delta_rps = (1 - 2 * sign) * (abs + 1); + + rps->num_neg_pics = 0; + rps->num_pos_pics = 0; + rps->num_pics = 0; + + for(i = 0 ; i <= ref_rps->num_pics; ++i) { + /* used_by_curr_pic_flag */ + if (!vl_rbsp_u(rbsp, 1)) + /* use_delta_flag */ + vl_rbsp_u(rbsp, 1); + else { + delta_poc = delta_rps + + ((i < ref_rps->num_pics)? ref_rps->delta_poc[i] : 0); + rps->delta_poc[rps->num_pics] = delta_poc; + rps->used[rps->num_pics] = true; + if (delta_poc < 0) + rps->num_neg_pics++; + else + rps->num_pos_pics++; + rps->num_pics++; + } + } + + rps->num_delta_poc = ref_rps->num_pics; + + /* sort delta poc */ + for (i = 1; i < rps->num_pics; ++i) { + delta_poc = rps->delta_poc[i]; + used = rps->used[i]; + for (j = i - 1; j >= 0; j--) { + if (delta_poc < rps->delta_poc[j]) { + rps->delta_poc[j + 1] = rps->delta_poc[j]; + rps->used[j + 1] = rps->used[j]; + rps->delta_poc[j] = delta_poc; + rps->used[j] = used; + } + } + } + + for (i = 0 , j = rps->num_neg_pics - 1; + i < rps->num_neg_pics >> 1; i++, j--) { + delta_poc = rps->delta_poc[i]; + used = rps->used[i]; + rps->delta_poc[i] = rps->delta_poc[j]; + rps->used[i] = rps->used[j]; + rps->delta_poc[j] = delta_poc; + rps->used[j] = used; + } + } else { + /* num_negative_pics */ + rps->num_neg_pics = vl_rbsp_ue(rbsp); + /* num_positive_pics */ + rps->num_pos_pics = vl_rbsp_ue(rbsp); + rps->num_pics = rps->num_neg_pics + rps->num_pos_pics; + + delta_poc = 0; + for(i = 0 ; i < rps->num_neg_pics; ++i) { + /* delta_poc_s0_minus1 */ + delta_poc -= (vl_rbsp_ue(rbsp) + 1); + rps->delta_poc[i] = delta_poc; + /* used_by_curr_pic_s0_flag */ + rps->used[i] = vl_rbsp_u(rbsp, 1); + } + + delta_poc = 0; + for(i = rps->num_neg_pics; i < rps->num_pics; ++i) { + /* delta_poc_s1_minus1 */ + delta_poc += (vl_rbsp_ue(rbsp) + 1); + rps->delta_poc[i] = delta_poc; + /* used_by_curr_pic_s1_flag */ + rps->used[i] = vl_rbsp_u(rbsp, 1); + } + } +} + +static struct pipe_h265_sps *seq_parameter_set_id(vid_dec_PrivateType *priv, + struct vl_rbsp *rbsp) +{ + unsigned id = vl_rbsp_ue(rbsp); + + if (id >= ARRAY_SIZE(priv->codec_data.h265.sps)) + return NULL; + + return &priv->codec_data.h265.sps[id]; +} + +static void seq_parameter_set(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp) +{ + struct pipe_h265_sps *sps; + int sps_max_sub_layers_minus1; + unsigned i; + + /* sps_video_parameter_set_id */ + vl_rbsp_u(rbsp, 4); + + /* sps_max_sub_layers_minus1 */ + sps_max_sub_layers_minus1 = vl_rbsp_u(rbsp, 3); + + assert(sps_max_sub_layers_minus1 <= 6); + + /* sps_temporal_id_nesting_flag */ + vl_rbsp_u(rbsp, 1); + + priv->codec_data.h265.level_idc = + profile_tier_level(rbsp, sps_max_sub_layers_minus1); + + sps = seq_parameter_set_id(priv, rbsp); + if (!sps) + return; + + memset(sps, 0, sizeof(*sps)); + + sps->chroma_format_idc = vl_rbsp_ue(rbsp); + + if (sps->chroma_format_idc == 3) + sps->separate_colour_plane_flag = vl_rbsp_u(rbsp, 1); + + priv->codec_data.h265.pic_width_in_luma_samples = + sps->pic_width_in_luma_samples = vl_rbsp_ue(rbsp); + + priv->codec_data.h265.pic_height_in_luma_samples = + sps->pic_height_in_luma_samples = vl_rbsp_ue(rbsp); + + /* conformance_window_flag */ + if (vl_rbsp_u(rbsp, 1)) { + /* conf_win_left_offset */ + vl_rbsp_ue(rbsp); + /* conf_win_right_offset */ + vl_rbsp_ue(rbsp); + /* conf_win_top_offset */ + vl_rbsp_ue(rbsp); + /* conf_win_bottom_offset */ + vl_rbsp_ue(rbsp); + } + + sps->bit_depth_luma_minus8 = vl_rbsp_ue(rbsp); + sps->bit_depth_chroma_minus8 = vl_rbsp_ue(rbsp); + sps->log2_max_pic_order_cnt_lsb_minus4 = vl_rbsp_ue(rbsp); + + /* sps_sub_layer_ordering_info_present_flag */ + i = vl_rbsp_u(rbsp, 1) ? 0 : sps_max_sub_layers_minus1; + for (; i <= sps_max_sub_layers_minus1; ++i) { + sps->sps_max_dec_pic_buffering_minus1 = vl_rbsp_ue(rbsp); + /* sps_max_num_reorder_pics */ + vl_rbsp_ue(rbsp); + /* sps_max_latency_increase_plus */ + vl_rbsp_ue(rbsp); + } + + sps->log2_min_luma_coding_block_size_minus3 = vl_rbsp_ue(rbsp); + sps->log2_diff_max_min_luma_coding_block_size = vl_rbsp_ue(rbsp); + sps->log2_min_transform_block_size_minus2 = vl_rbsp_ue(rbsp); + sps->log2_diff_max_min_transform_block_size = vl_rbsp_ue(rbsp); + sps->max_transform_hierarchy_depth_inter = vl_rbsp_ue(rbsp); + sps->max_transform_hierarchy_depth_intra = vl_rbsp_ue(rbsp); + + sps->scaling_list_enabled_flag = vl_rbsp_u(rbsp, 1); + if (sps->scaling_list_enabled_flag) + /* sps_scaling_list_data_present_flag */ + if (vl_rbsp_u(rbsp, 1)) + scaling_list_data(priv, rbsp, sps); + + sps->amp_enabled_flag = vl_rbsp_u(rbsp, 1); + sps->sample_adaptive_offset_enabled_flag = vl_rbsp_u(rbsp, 1); + sps->pcm_enabled_flag = vl_rbsp_u(rbsp, 1); + if (sps->pcm_enabled_flag) { + sps->pcm_sample_bit_depth_luma_minus1 = vl_rbsp_u(rbsp, 4); + sps->pcm_sample_bit_depth_chroma_minus1 = vl_rbsp_u(rbsp, 4); + sps->log2_min_pcm_luma_coding_block_size_minus3 = vl_rbsp_ue(rbsp); + sps->log2_diff_max_min_pcm_luma_coding_block_size = vl_rbsp_ue(rbsp); + sps->pcm_loop_filter_disabled_flag = vl_rbsp_u(rbsp, 1); + } + + sps->num_short_term_ref_pic_sets = vl_rbsp_ue(rbsp); + + for (i = 0; i < sps->num_short_term_ref_pic_sets; ++i) { + struct ref_pic_set *rps; + + rps = (struct ref_pic_set *) + priv->codec_data.h265.ref_pic_set_list + i; + st_ref_pic_set(priv, rbsp, rps, sps, i); + } + + sps->long_term_ref_pics_present_flag = vl_rbsp_u(rbsp, 1); + if (sps->long_term_ref_pics_present_flag) { + sps->num_long_term_ref_pics_sps = vl_rbsp_ue(rbsp); + for (i = 0; i < sps->num_long_term_ref_pics_sps; ++i) { + /* lt_ref_pic_poc_lsb_sps */ + vl_rbsp_u(rbsp, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + /* used_by_curr_pic_lt_sps_flag */ + vl_rbsp_u(rbsp, 1); + } + } + + sps->sps_temporal_mvp_enabled_flag = vl_rbsp_u(rbsp, 1); + sps->strong_intra_smoothing_enabled_flag = vl_rbsp_u(rbsp, 1); +} + +static struct pipe_h265_pps *pic_parameter_set_id(vid_dec_PrivateType *priv, + struct vl_rbsp *rbsp) +{ + unsigned id = vl_rbsp_ue(rbsp); + + if (id >= ARRAY_SIZE(priv->codec_data.h265.pps)) + return NULL; + + return &priv->codec_data.h265.pps[id]; +} + +static void picture_parameter_set(vid_dec_PrivateType *priv, + struct vl_rbsp *rbsp) +{ + struct pipe_h265_sps *sps; + struct pipe_h265_pps *pps; + int i; + + pps = pic_parameter_set_id(priv, rbsp); + if (!pps) + return; + + memset(pps, 0, sizeof(*pps)); + sps = pps->sps = seq_parameter_set_id(priv, rbsp); + if (!sps) + return; + + pps->dependent_slice_segments_enabled_flag = vl_rbsp_u(rbsp, 1); + pps->output_flag_present_flag = vl_rbsp_u(rbsp, 1); + pps->num_extra_slice_header_bits = vl_rbsp_u(rbsp, 3); + pps->sign_data_hiding_enabled_flag = vl_rbsp_u(rbsp, 1); + pps->cabac_init_present_flag = vl_rbsp_u(rbsp, 1); + + pps->num_ref_idx_l0_default_active_minus1 = vl_rbsp_ue(rbsp); + pps->num_ref_idx_l1_default_active_minus1 = vl_rbsp_ue(rbsp); + pps->init_qp_minus26 = vl_rbsp_se(rbsp); + pps->constrained_intra_pred_flag = vl_rbsp_u(rbsp, 1); + pps->transform_skip_enabled_flag = vl_rbsp_u(rbsp, 1); + + pps->cu_qp_delta_enabled_flag = vl_rbsp_u(rbsp, 1); + if (pps->cu_qp_delta_enabled_flag) + pps->diff_cu_qp_delta_depth = vl_rbsp_ue(rbsp); + + pps->pps_cb_qp_offset = vl_rbsp_se(rbsp); + pps->pps_cr_qp_offset = vl_rbsp_se(rbsp); + pps->pps_slice_chroma_qp_offsets_present_flag = vl_rbsp_u(rbsp, 1); + + pps->weighted_pred_flag = vl_rbsp_u(rbsp, 1); + pps->weighted_bipred_flag = vl_rbsp_u(rbsp, 1); + + pps->transquant_bypass_enabled_flag = vl_rbsp_u(rbsp, 1); + pps->tiles_enabled_flag = vl_rbsp_u(rbsp, 1); + pps->entropy_coding_sync_enabled_flag = vl_rbsp_u(rbsp, 1); + + if (pps->tiles_enabled_flag) { + pps->num_tile_columns_minus1 = vl_rbsp_ue(rbsp); + pps->num_tile_rows_minus1 = vl_rbsp_ue(rbsp); + + pps->uniform_spacing_flag = vl_rbsp_u(rbsp, 1); + if (!pps->uniform_spacing_flag) { + for (i = 0; i < pps->num_tile_columns_minus1; ++i) + pps->column_width_minus1[i] = vl_rbsp_ue(rbsp); + + for (i = 0; i < pps->num_tile_rows_minus1; ++i) + pps->row_height_minus1[i] = vl_rbsp_ue(rbsp); + } + + if (!pps->num_tile_columns_minus1 || !pps->num_tile_rows_minus1) + pps->loop_filter_across_tiles_enabled_flag = vl_rbsp_u(rbsp, 1); + } + + pps->pps_loop_filter_across_slices_enabled_flag = vl_rbsp_u(rbsp, 1); + + pps->deblocking_filter_control_present_flag = vl_rbsp_u(rbsp, 1); + if (pps->deblocking_filter_control_present_flag) { + pps->deblocking_filter_override_enabled_flag = vl_rbsp_u(rbsp, 1); + pps->pps_deblocking_filter_disabled_flag = vl_rbsp_u(rbsp, 1); + if (!pps->pps_deblocking_filter_disabled_flag) { + pps->pps_beta_offset_div2 = vl_rbsp_se(rbsp); + pps->pps_tc_offset_div2 = vl_rbsp_se(rbsp); + } + } + + /* pps_scaling_list_data_present_flag */ + if (vl_rbsp_u(rbsp, 1)) + scaling_list_data(priv, rbsp, sps); + + pps->lists_modification_present_flag = vl_rbsp_u(rbsp, 1); + pps->log2_parallel_merge_level_minus2 = vl_rbsp_ue(rbsp); + pps->slice_segment_header_extension_present_flag = vl_rbsp_u(rbsp, 1); +} + +static void vid_dec_h265_BeginFrame(vid_dec_PrivateType *priv) +{ + if (priv->frame_started) + return; + + if (!priv->codec) { + struct pipe_video_codec templat = {}; + omx_base_video_PortType *port = (omx_base_video_PortType *) + priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; + + templat.profile = priv->profile; + templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + templat.expect_chunked_decode = true; + templat.width = priv->codec_data.h265.pic_width_in_luma_samples; + templat.height = priv->codec_data.h265.pic_height_in_luma_samples; + templat.level = priv->codec_data.h265.level_idc; + priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat); + + /* disable transcode tunnel if video size is different from coded size */ + if (priv->codec_data.h265.pic_width_in_luma_samples != + port->sPortParam.format.video.nFrameWidth || + priv->codec_data.h265.pic_height_in_luma_samples != + port->sPortParam.format.video.nFrameHeight) + priv->disable_tunnel = true; + } + + vid_dec_NeedTarget(priv); + + if (priv->first_buf_in_frame) + priv->timestamp = priv->timestamps[0]; + priv->first_buf_in_frame = false; + + priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base); + priv->frame_started = true; +} + +static struct pipe_video_buffer *vid_dec_h265_Flush(vid_dec_PrivateType *priv, + OMX_TICKS *timestamp) +{ + struct dpb_list *entry, *result = NULL; + struct pipe_video_buffer *buf; + + /* search for the lowest poc and break on zeros */ + LIST_FOR_EACH_ENTRY(entry, &priv->codec_data.h265.dpb_list, list) { + + if (result && entry->poc == 0) + break; + + if (!result || entry->poc < result->poc) + result = entry; + } + + if (!result) + return NULL; + + buf = result->buffer; + if (timestamp) + *timestamp = result->timestamp; + + --priv->codec_data.h265.dpb_num; + LIST_DEL(&result->list); + FREE(result); + + return buf; +} + +static void vid_dec_h265_EndFrame(vid_dec_PrivateType *priv) +{ + struct dpb_list *entry = NULL; + struct pipe_video_buffer *tmp; + struct ref_pic_set *rps; + int i; + OMX_TICKS timestamp; + + if (!priv->frame_started) + return; + + priv->picture.h265.NumPocStCurrBefore = 0; + priv->picture.h265.NumPocStCurrAfter = 0; + memset(priv->picture.h265.RefPicSetStCurrBefore, 0, 8); + memset(priv->picture.h265.RefPicSetStCurrAfter, 0, 8); + for (i = 0; i < MAX_NUM_REF_PICS; ++i) { + priv->picture.h265.ref[i] = NULL; + priv->picture.h265.PicOrderCntVal[i] = 0; + } + + rps = priv->codec_data.h265.rps; + + if (rps) { + unsigned bf = 0, af = 0; + + priv->picture.h265.NumDeltaPocsOfRefRpsIdx = rps->num_delta_poc; + for (i = 0; i < rps->num_pics; ++i) { + priv->picture.h265.PicOrderCntVal[i] = + rps->delta_poc[i] + get_poc(priv); + + LIST_FOR_EACH_ENTRY(entry, &priv->codec_data.h265.dpb_list, list) { + if (entry->poc == priv->picture.h265.PicOrderCntVal[i]) { + priv->picture.h265.ref[i] = entry->buffer; + break; + } + } + + if (rps->used[i]) { + if (i < rps->num_neg_pics) { + priv->picture.h265.NumPocStCurrBefore++; + priv->picture.h265.RefPicSetStCurrBefore[bf++] = i; + } else { + priv->picture.h265.NumPocStCurrAfter++; + priv->picture.h265.RefPicSetStCurrAfter[af++] = i; + } + } + } + } + + priv->codec->end_frame(priv->codec, priv->target, &priv->picture.base); + priv->frame_started = false; + + /* add the decoded picture to the dpb list */ + entry = CALLOC_STRUCT(dpb_list); + if (!entry) + return; + + priv->first_buf_in_frame = true; + entry->buffer = priv->target; + entry->timestamp = priv->timestamp; + entry->poc = get_poc(priv); + + LIST_ADDTAIL(&entry->list, &priv->codec_data.h265.dpb_list); + ++priv->codec_data.h265.dpb_num; + priv->target = NULL; + + if (priv->codec_data.h265.dpb_num <= DPB_MAX_SIZE) + return; + + tmp = priv->in_buffers[0]->pInputPortPrivate; + priv->in_buffers[0]->pInputPortPrivate = vid_dec_h265_Flush(priv, ×tamp); + priv->in_buffers[0]->nTimeStamp = timestamp; + priv->target = tmp; + priv->frame_finished = priv->in_buffers[0]->pInputPortPrivate != NULL; + if (priv->frame_finished && + (priv->in_buffers[0]->nFlags & OMX_BUFFERFLAG_EOS)) + FREE(priv->codec_data.h265.ref_pic_set_list); +} + +static void slice_header(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp, + unsigned nal_unit_type) +{ + struct pipe_h265_pps *pps; + struct pipe_h265_sps *sps; + bool first_slice_segment_in_pic_flag; + bool dependent_slice_segment_flag = false; + struct ref_pic_set *rps; + unsigned poc_lsb, poc_msb, slice_prev_poc; + unsigned max_poc_lsb, prev_poc_lsb, prev_poc_msb; + unsigned num_st_rps; + int i; + + if (priv->picture.h265.IDRPicFlag != is_idr_picture(nal_unit_type)) + vid_dec_h265_EndFrame(priv); + + priv->picture.h265.IDRPicFlag = is_idr_picture(nal_unit_type); + + first_slice_segment_in_pic_flag = vl_rbsp_u(rbsp, 1); + + if (is_rap_picture(nal_unit_type)) + /* no_output_of_prior_pics_flag */ + vl_rbsp_u(rbsp, 1); + + pps = pic_parameter_set_id(priv, rbsp); + if (!pps) + return; + + sps = pps->sps; + if (!sps) + return; + + if (pps != priv->picture.h265.pps) + vid_dec_h265_EndFrame(priv); + + priv->picture.h265.pps = pps; + + if (priv->picture.h265.RAPPicFlag != is_rap_picture(nal_unit_type)) + vid_dec_h265_EndFrame(priv); + priv->picture.h265.RAPPicFlag = is_rap_picture(nal_unit_type); + + num_st_rps = sps->num_short_term_ref_pic_sets; + + if (priv->picture.h265.CurrRpsIdx != num_st_rps) + vid_dec_h265_EndFrame(priv); + priv->picture.h265.CurrRpsIdx = num_st_rps; + + if (!first_slice_segment_in_pic_flag) { + int size, num; + int bits_slice_segment_address = 0; + + if (pps->dependent_slice_segments_enabled_flag) + dependent_slice_segment_flag = vl_rbsp_u(rbsp, 1); + + size = 1 << (sps->log2_min_luma_coding_block_size_minus3 + 3 + + sps->log2_diff_max_min_luma_coding_block_size); + + num = ((sps->pic_width_in_luma_samples + size - 1) / size) * + ((sps->pic_height_in_luma_samples + size - 1) / size); + + while (num > (1 << bits_slice_segment_address)) + bits_slice_segment_address++; + + /* slice_segment_address */ + vl_rbsp_u(rbsp, bits_slice_segment_address); + } + + if (dependent_slice_segment_flag) + return; + + for (i = 0; i < pps->num_extra_slice_header_bits; ++i) + /* slice_reserved_flag */ + vl_rbsp_u(rbsp, 1); + + /* slice_type */ + vl_rbsp_ue(rbsp); + + if (pps->output_flag_present_flag) + /* pic output flag */ + vl_rbsp_u(rbsp, 1); + + if (sps->separate_colour_plane_flag) + /* colour_plane_id */ + vl_rbsp_u(rbsp, 2); + + if (is_idr_picture(nal_unit_type)) { + set_poc(priv, nal_unit_type, 0); + return; + } + + /* slice_pic_order_cnt_lsb */ + poc_lsb = + vl_rbsp_u(rbsp, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + + slice_prev_poc = (int)priv->codec_data.h265.slice_prev_poc; + max_poc_lsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + + prev_poc_lsb = slice_prev_poc & (max_poc_lsb - 1); + prev_poc_msb = slice_prev_poc - prev_poc_lsb; + + if ((poc_lsb < prev_poc_lsb) && + ((prev_poc_lsb - poc_lsb ) >= (max_poc_lsb / 2))) + poc_msb = prev_poc_msb + max_poc_lsb; + + else if ((poc_lsb > prev_poc_lsb ) && + ((poc_lsb - prev_poc_lsb) > (max_poc_lsb / 2))) + poc_msb = prev_poc_msb - max_poc_lsb; + + else + poc_msb = prev_poc_msb; + + if (is_bla_picture(nal_unit_type)) + poc_msb = 0; + + if (get_poc(priv) != poc_msb + poc_lsb) + vid_dec_h265_EndFrame(priv); + + set_poc(priv, nal_unit_type, (poc_msb + poc_lsb)); + + /* short_term_ref_pic_set_sps_flag */ + if (!vl_rbsp_u(rbsp, 1)) { + rps = (struct ref_pic_set *) + priv->codec_data.h265.ref_pic_set_list + num_st_rps; + st_ref_pic_set(priv, rbsp, rps, sps, num_st_rps); + + } else if (num_st_rps > 1) { + int num_bits = 0; + unsigned idx; + + while ((1 << num_bits) < num_st_rps) + num_bits++; + + if (num_bits > 0) + /* short_term_ref_pic_set_idx */ + idx = vl_rbsp_u(rbsp, num_bits); + else + idx = 0; + + rps = (struct ref_pic_set *) + priv->codec_data.h265.ref_pic_set_list + idx; + } else + rps = (struct ref_pic_set *) + priv->codec_data.h265.ref_pic_set_list; + + if (is_bla_picture(nal_unit_type)) { + rps->num_neg_pics = 0; + rps->num_pos_pics = 0; + rps->num_pics = 0; + } + + priv->codec_data.h265.rps = rps; + + return; +} + +static void vid_dec_h265_Decode(vid_dec_PrivateType *priv, + struct vl_vlc *vlc, + unsigned min_bits_left) +{ + unsigned nal_unit_type; + unsigned nuh_layer_id; + unsigned nuh_temporal_id_plus1; + + if (!vl_vlc_search_byte(vlc, vl_vlc_bits_left(vlc) - min_bits_left, 0x00)) + return; + + if (vl_vlc_peekbits(vlc, 24) != 0x000001) { + vl_vlc_eatbits(vlc, 8); + return; + } + + if (priv->slice) { + unsigned bytes = priv->bytes_left - (vl_vlc_bits_left(vlc) / 8); + + priv->codec->decode_bitstream(priv->codec, priv->target, + &priv->picture.base, 1, + &priv->slice, &bytes); + priv->slice = NULL; + } + + vl_vlc_eatbits(vlc, 24); + + /* forbidden_zero_bit */ + vl_vlc_eatbits(vlc, 1); + + if (vl_vlc_valid_bits(vlc) < 15) + vl_vlc_fillbits(vlc); + + nal_unit_type = vl_vlc_get_uimsbf(vlc, 6); + + /* nuh_layer_id */ + nuh_layer_id = vl_vlc_get_uimsbf(vlc, 6); + + /* nuh_temporal_id_plus1 */ + nuh_temporal_id_plus1 = vl_vlc_get_uimsbf(vlc, 3); + priv->codec_data.h265.temporal_id = nuh_temporal_id_plus1 - 1; + + if (!is_slice_picture(nal_unit_type)) + vid_dec_h265_EndFrame(priv); + + if (nal_unit_type == NAL_UNIT_TYPE_SPS) { + struct vl_rbsp rbsp; + + vl_rbsp_init(&rbsp, vlc, ~0); + seq_parameter_set(priv, &rbsp); + + } else if (nal_unit_type == NAL_UNIT_TYPE_PPS) { + struct vl_rbsp rbsp; + + vl_rbsp_init(&rbsp, vlc, ~0); + picture_parameter_set(priv, &rbsp); + + } else if (is_slice_picture(nal_unit_type)) { + unsigned bits = vl_vlc_valid_bits(vlc); + unsigned bytes = bits / 8 + 5; + struct vl_rbsp rbsp; + uint8_t buf[9]; + const void *ptr = buf; + unsigned i; + + buf[0] = 0x0; + buf[1] = 0x0; + buf[2] = 0x1; + buf[3] = nal_unit_type << 1 | nuh_layer_id >> 5; + buf[4] = nuh_layer_id << 3 | nuh_temporal_id_plus1; + for (i = 5; i < bytes; ++i) + buf[i] = vl_vlc_peekbits(vlc, bits) >> ((bytes - i - 1) * 8); + + priv->bytes_left = (vl_vlc_bits_left(vlc) - bits) / 8; + priv->slice = vlc->data; + + vl_rbsp_init(&rbsp, vlc, 128); + slice_header(priv, &rbsp, nal_unit_type); + + vid_dec_h265_BeginFrame(priv); + + priv->codec->decode_bitstream(priv->codec, priv->target, + &priv->picture.base, 1, + &ptr, &bytes); + } + + /* resync to byte boundary */ + vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8); +} + +void vid_dec_h265_Init(vid_dec_PrivateType *priv) +{ + priv->picture.base.profile = PIPE_VIDEO_PROFILE_HEVC_MAIN; + + LIST_INITHEAD(&priv->codec_data.h265.dpb_list); + priv->codec_data.h265.ref_pic_set_list = (struct ref_pic_set *) + CALLOC(MAX_NUM_REF_PICS, sizeof(struct ref_pic_set)); + + priv->Decode = vid_dec_h265_Decode; + priv->EndFrame = vid_dec_h265_EndFrame; + priv->Flush = vid_dec_h265_Flush; + priv->first_buf_in_frame = true; +} diff --git a/src/gallium/state_trackers/omx_bellagio/vid_dec_mpeg12.c b/src/gallium/state_trackers/omx_bellagio/vid_dec_mpeg12.c new file mode 100644 index 00000000000..7b2df8f40fa --- /dev/null +++ b/src/gallium/state_trackers/omx_bellagio/vid_dec_mpeg12.c @@ -0,0 +1,383 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Authors: + * Christian König + * + */ + +#include "pipe/p_video_codec.h" +#include "vl/vl_vlc.h" +#include "vl/vl_zscan.h" + +#include "vid_dec.h" + +static uint8_t default_intra_matrix[64] = { + 8, 16, 19, 22, 26, 27, 29, 34, + 16, 16, 19, 22, 22, 22, 22, 26, + 26, 27, 22, 26, 26, 27, 29, 24, + 27, 27, 29, 32, 27, 29, 29, 32, + 35, 29, 34, 34, 35, 40, 34, 34, + 37, 40, 48, 37, 38, 40, 48, 58, + 26, 27, 29, 34, 38, 46, 56, 69, + 27, 29, 35, 38, 46, 56, 69, 83 +}; + +static uint8_t default_non_intra_matrix[64] = { + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16 +}; + +static void vid_dec_mpeg12_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left); +static void vid_dec_mpeg12_EndFrame(vid_dec_PrivateType *priv); +static struct pipe_video_buffer *vid_dec_mpeg12_Flush(vid_dec_PrivateType *priv, OMX_TICKS *timestamp); + +void vid_dec_mpeg12_Init(vid_dec_PrivateType *priv) +{ + struct pipe_video_codec templat = {}; + omx_base_video_PortType *port; + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; + templat.profile = priv->profile; + templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_BITSTREAM; + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + templat.max_references = 2; + templat.expect_chunked_decode = true; + templat.width = port->sPortParam.format.video.nFrameWidth; + templat.height = port->sPortParam.format.video.nFrameHeight; + + priv->codec = priv->pipe->create_video_codec(priv->pipe, &templat); + + priv->picture.base.profile = PIPE_VIDEO_PROFILE_MPEG2_MAIN; + priv->picture.mpeg12.intra_matrix = default_intra_matrix; + priv->picture.mpeg12.non_intra_matrix = default_non_intra_matrix; + + priv->Decode = vid_dec_mpeg12_Decode; + priv->EndFrame = vid_dec_mpeg12_EndFrame; + priv->Flush = vid_dec_mpeg12_Flush; +} + +static void BeginFrame(vid_dec_PrivateType *priv) +{ + if (priv->picture.mpeg12.picture_coding_type != PIPE_MPEG12_PICTURE_CODING_TYPE_B) { + priv->picture.mpeg12.ref[0] = priv->picture.mpeg12.ref[1]; + priv->picture.mpeg12.ref[1] = NULL; + } + + if (priv->target == priv->picture.mpeg12.ref[0]) { + struct pipe_video_buffer *tmp = priv->target; + priv->target = priv->shadow; + priv->shadow = tmp; + } + + vid_dec_NeedTarget(priv); + + priv->codec->begin_frame(priv->codec, priv->target, &priv->picture.base); + priv->frame_started = true; +} + +static void vid_dec_mpeg12_EndFrame(vid_dec_PrivateType *priv) +{ + struct pipe_video_buffer *done; + + priv->codec->end_frame(priv->codec, priv->target, &priv->picture.base); + priv->frame_started = false; + + if (priv->picture.mpeg12.picture_coding_type != PIPE_MPEG12_PICTURE_CODING_TYPE_B) { + + priv->picture.mpeg12.ref[1] = priv->target; + done = priv->picture.mpeg12.ref[0]; + if (!done) { + priv->target = NULL; + return; + } + + } else + done = priv->target; + + priv->frame_finished = true; + priv->target = priv->in_buffers[0]->pInputPortPrivate; + priv->in_buffers[0]->pInputPortPrivate = done; +} + +static struct pipe_video_buffer *vid_dec_mpeg12_Flush(vid_dec_PrivateType *priv, OMX_TICKS *timestamp) +{ + struct pipe_video_buffer *result = priv->picture.mpeg12.ref[1]; + priv->picture.mpeg12.ref[1] = NULL; + if (timestamp) + *timestamp = OMX_VID_DEC_TIMESTAMP_INVALID; + return result; +} + +static void vid_dec_mpeg12_Decode(vid_dec_PrivateType *priv, struct vl_vlc *vlc, unsigned min_bits_left) +{ + uint8_t code; + unsigned i; + + if (!vl_vlc_search_byte(vlc, vl_vlc_bits_left(vlc) - min_bits_left, 0x00)) + return; + + if (vl_vlc_peekbits(vlc, 24) != 0x000001) { + vl_vlc_eatbits(vlc, 8); + return; + } + + if (priv->slice) { + unsigned bytes = priv->bytes_left - (vl_vlc_bits_left(vlc) / 8); + priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, + 1, &priv->slice, &bytes); + priv->slice = NULL; + } + + vl_vlc_eatbits(vlc, 24); + code = vl_vlc_get_uimsbf(vlc, 8); + + if (priv->frame_started && (code == 0x00 || code > 0xAF)) + vid_dec_mpeg12_EndFrame(priv); + + if (code == 0xB3) { + /* sequence header code */ + vl_vlc_fillbits(vlc); + + /* horizontal_size_value */ + vl_vlc_get_uimsbf(vlc, 12); + + /* vertical_size_value */ + vl_vlc_get_uimsbf(vlc, 12); + + /* aspect_ratio_information */ + vl_vlc_get_uimsbf(vlc, 4); + + /* frame_rate_code */ + vl_vlc_get_uimsbf(vlc, 4); + + vl_vlc_fillbits(vlc); + + /* bit_rate_value */ + vl_vlc_get_uimsbf(vlc, 18); + + /* marker_bit */ + vl_vlc_get_uimsbf(vlc, 1); + + /* vbv_buffer_size_value */ + vl_vlc_get_uimsbf(vlc, 10); + + /* constrained_parameters_flag */ + vl_vlc_get_uimsbf(vlc, 1); + + vl_vlc_fillbits(vlc); + + /* load_intra_quantiser_matrix */ + if (vl_vlc_get_uimsbf(vlc, 1)) { + /* intra_quantiser_matrix */ + priv->picture.mpeg12.intra_matrix = priv->codec_data.mpeg12.intra_matrix; + for (i = 0; i < 64; ++i) { + priv->codec_data.mpeg12.intra_matrix[vl_zscan_normal[i]] = vl_vlc_get_uimsbf(vlc, 8); + vl_vlc_fillbits(vlc); + } + } else + priv->picture.mpeg12.intra_matrix = default_intra_matrix; + + /* load_non_intra_quantiser_matrix */ + if (vl_vlc_get_uimsbf(vlc, 1)) { + /* non_intra_quantiser_matrix */ + priv->picture.mpeg12.non_intra_matrix = priv->codec_data.mpeg12.non_intra_matrix; + for (i = 0; i < 64; ++i) { + priv->codec_data.mpeg12.non_intra_matrix[i] = vl_vlc_get_uimsbf(vlc, 8); + vl_vlc_fillbits(vlc); + } + } else + priv->picture.mpeg12.non_intra_matrix = default_non_intra_matrix; + + } else if (code == 0x00) { + /* picture start code */ + vl_vlc_fillbits(vlc); + + /* temporal_reference */ + vl_vlc_get_uimsbf(vlc, 10); + + priv->picture.mpeg12.picture_coding_type = vl_vlc_get_uimsbf(vlc, 3); + + /* vbv_delay */ + vl_vlc_get_uimsbf(vlc, 16); + + vl_vlc_fillbits(vlc); + if (priv->picture.mpeg12.picture_coding_type == 2 || + priv->picture.mpeg12.picture_coding_type == 3) { + priv->picture.mpeg12.full_pel_forward_vector = vl_vlc_get_uimsbf(vlc, 1); + /* forward_f_code */ + priv->picture.mpeg12.f_code[0][0] = vl_vlc_get_uimsbf(vlc, 3) - 1; + priv->picture.mpeg12.f_code[0][1] = priv->picture.mpeg12.f_code[0][0]; + } else { + priv->picture.mpeg12.full_pel_forward_vector = 0; + priv->picture.mpeg12.f_code[0][1] = priv->picture.mpeg12.f_code[0][0] = 14; + } + + if (priv->picture.mpeg12.picture_coding_type == 3) { + priv->picture.mpeg12.full_pel_backward_vector = vl_vlc_get_uimsbf(vlc, 1); + /* backward_f_code */ + priv->picture.mpeg12.f_code[1][0] = vl_vlc_get_uimsbf(vlc, 3) - 1; + priv->picture.mpeg12.f_code[1][1] = priv->picture.mpeg12.f_code[1][0]; + } else { + priv->picture.mpeg12.full_pel_backward_vector = 0; + priv->picture.mpeg12.f_code[0][1] = priv->picture.mpeg12.f_code[0][0] = 14; + } + + /* extra_bit_picture */ + while (vl_vlc_get_uimsbf(vlc, 1)) { + /* extra_information_picture */ + vl_vlc_get_uimsbf(vlc, 8); + vl_vlc_fillbits(vlc); + } + + } else if (code == 0xB5) { + /* extension start code */ + vl_vlc_fillbits(vlc); + + /* extension_start_code_identifier */ + switch (vl_vlc_get_uimsbf(vlc, 4)) { + case 0x3: /* quant matrix extension */ + + /* load_intra_quantiser_matrix */ + if (vl_vlc_get_uimsbf(vlc, 1)) { + /* intra_quantiser_matrix */ + priv->picture.mpeg12.intra_matrix = priv->codec_data.mpeg12.intra_matrix; + for (i = 0; i < 64; ++i) { + priv->codec_data.mpeg12.intra_matrix[vl_zscan_normal[i]] = vl_vlc_get_uimsbf(vlc, 8); + vl_vlc_fillbits(vlc); + } + } else + priv->picture.mpeg12.intra_matrix = default_intra_matrix; + + /* load_non_intra_quantiser_matrix */ + if (vl_vlc_get_uimsbf(vlc, 1)) { + /* non_intra_quantiser_matrix */ + priv->picture.mpeg12.non_intra_matrix = priv->codec_data.mpeg12.non_intra_matrix; + for (i = 0; i < 64; ++i) { + priv->codec_data.mpeg12.non_intra_matrix[i] = vl_vlc_get_uimsbf(vlc, 8); + vl_vlc_fillbits(vlc); + } + } else + priv->picture.mpeg12.intra_matrix = default_non_intra_matrix; + + break; + + case 0x8: /* picture coding extension */ + + priv->picture.mpeg12.f_code[0][0] = vl_vlc_get_uimsbf(vlc, 4) - 1; + priv->picture.mpeg12.f_code[0][1] = vl_vlc_get_uimsbf(vlc, 4) - 1; + priv->picture.mpeg12.f_code[1][0] = vl_vlc_get_uimsbf(vlc, 4) - 1; + priv->picture.mpeg12.f_code[1][1] = vl_vlc_get_uimsbf(vlc, 4) - 1; + priv->picture.mpeg12.intra_dc_precision = vl_vlc_get_uimsbf(vlc, 2); + priv->picture.mpeg12.picture_structure = vl_vlc_get_uimsbf(vlc, 2); + priv->picture.mpeg12.top_field_first = vl_vlc_get_uimsbf(vlc, 1); + priv->picture.mpeg12.frame_pred_frame_dct = vl_vlc_get_uimsbf(vlc, 1); + priv->picture.mpeg12.concealment_motion_vectors = vl_vlc_get_uimsbf(vlc, 1); + priv->picture.mpeg12.q_scale_type = vl_vlc_get_uimsbf(vlc, 1); + priv->picture.mpeg12.intra_vlc_format = vl_vlc_get_uimsbf(vlc, 1); + priv->picture.mpeg12.alternate_scan = vl_vlc_get_uimsbf(vlc, 1); + + /* repeat_first_field */ + vl_vlc_get_uimsbf(vlc, 1); + + /* chroma_420_type */ + vl_vlc_get_uimsbf(vlc, 1); + + vl_vlc_fillbits(vlc); + + /* progressive_frame */ + vl_vlc_get_uimsbf(vlc, 1); + + /* composite_display_flag */ + if (vl_vlc_get_uimsbf(vlc, 1)) { + + /* v_axis */ + vl_vlc_get_uimsbf(vlc, 1); + + /* field_sequence */ + vl_vlc_get_uimsbf(vlc, 3); + + /* sub_carrier */ + vl_vlc_get_uimsbf(vlc, 1); + + /* burst_amplitude */ + vl_vlc_get_uimsbf(vlc, 7); + + /* sub_carrier_phase */ + vl_vlc_get_uimsbf(vlc, 8); + } + break; + } + + } else if (code <= 0xAF) { + /* slice start */ + unsigned bytes = (vl_vlc_valid_bits(vlc) / 8) + 4; + uint8_t buf[12]; + const void *ptr = buf; + unsigned i; + + if (!priv->frame_started) + BeginFrame(priv); + + buf[0] = 0x00; + buf[1] = 0x00; + buf[2] = 0x01; + buf[3] = code; + for (i = 4; i < bytes; ++i) + buf[i] = vl_vlc_get_uimsbf(vlc, 8); + + priv->codec->decode_bitstream(priv->codec, priv->target, &priv->picture.base, + 1, &ptr, &bytes); + + priv->bytes_left = vl_vlc_bits_left(vlc) / 8; + priv->slice = vlc->data; + + } else if (code == 0xB2) { + /* user data start */ + + } else if (code == 0xB4) { + /* sequence error */ + } else if (code == 0xB7) { + /* sequence end */ + } else if (code == 0xB8) { + /* group start */ + } else if (code >= 0xB9) { + /* system start */ + } else { + /* reserved */ + } + + /* resync to byte boundary */ + vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8); +} diff --git a/src/gallium/state_trackers/omx_bellagio/vid_enc.c b/src/gallium/state_trackers/omx_bellagio/vid_enc.c new file mode 100644 index 00000000000..1a4fb62d408 --- /dev/null +++ b/src/gallium/state_trackers/omx_bellagio/vid_enc.c @@ -0,0 +1,1278 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Authors: + * Christian König + * + */ + + +#include + +#include + +/* bellagio defines a DEBUG macro that we don't want */ +#ifndef DEBUG +#include +#undef DEBUG +#else +#include +#endif + +#include + +#include "pipe/p_screen.h" +#include "pipe/p_video_codec.h" +#include "util/u_memory.h" +#include "vl/vl_video_buffer.h" + +#include "entrypoint.h" +#include "vid_enc.h" + +struct encode_task { + struct list_head list; + + struct pipe_video_buffer *buf; + unsigned pic_order_cnt; + struct pipe_resource *bitstream; + void *feedback; +}; + +struct input_buf_private { + struct list_head tasks; + + struct pipe_resource *resource; + struct pipe_transfer *transfer; +}; + +struct output_buf_private { + struct pipe_resource *bitstream; + struct pipe_transfer *transfer; +}; + +static OMX_ERRORTYPE vid_enc_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name); +static OMX_ERRORTYPE vid_enc_Destructor(OMX_COMPONENTTYPE *comp); +static OMX_ERRORTYPE vid_enc_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param); +static OMX_ERRORTYPE vid_enc_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param); +static OMX_ERRORTYPE vid_enc_SetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config); +static OMX_ERRORTYPE vid_enc_GetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config); +static OMX_ERRORTYPE vid_enc_MessageHandler(OMX_COMPONENTTYPE *comp, internalRequestMessageType *msg); +static OMX_ERRORTYPE vid_enc_AllocateInBuffer(omx_base_PortType *port, OMX_INOUT OMX_BUFFERHEADERTYPE **buf, + OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size); +static OMX_ERRORTYPE vid_enc_UseInBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE **buf, OMX_U32 idx, + OMX_PTR private, OMX_U32 size, OMX_U8 *mem); +static OMX_ERRORTYPE vid_enc_FreeInBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf); +static OMX_ERRORTYPE vid_enc_EncodeFrame(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf); +static OMX_ERRORTYPE vid_enc_AllocateOutBuffer(omx_base_PortType *comp, OMX_INOUT OMX_BUFFERHEADERTYPE **buf, + OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size); +static OMX_ERRORTYPE vid_enc_FreeOutBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf); +static void vid_enc_BufferEncoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output); + +static void enc_ReleaseTasks(struct list_head *head); + +OMX_ERRORTYPE vid_enc_LoaderComponent(stLoaderComponentType *comp) +{ + comp->componentVersion.s.nVersionMajor = 0; + comp->componentVersion.s.nVersionMinor = 0; + comp->componentVersion.s.nRevision = 0; + comp->componentVersion.s.nStep = 1; + comp->name_specific_length = 1; + comp->constructor = vid_enc_Constructor; + + comp->name = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); + if (!comp->name) + return OMX_ErrorInsufficientResources; + + comp->name_specific = CALLOC(1, sizeof(char *)); + if (!comp->name_specific) + goto error_arrays; + + comp->role_specific = CALLOC(1, sizeof(char *)); + if (!comp->role_specific) + goto error_arrays; + + comp->name_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); + if (comp->name_specific[0] == NULL) + goto error_specific; + + comp->role_specific[0] = CALLOC(1, OMX_MAX_STRINGNAME_SIZE); + if (comp->role_specific[0] == NULL) + goto error_specific; + + strcpy(comp->name, OMX_VID_ENC_BASE_NAME); + strcpy(comp->name_specific[0], OMX_VID_ENC_AVC_NAME); + strcpy(comp->role_specific[0], OMX_VID_ENC_AVC_ROLE); + + return OMX_ErrorNone; + +error_specific: + FREE(comp->role_specific[0]); + FREE(comp->name_specific[0]); + +error_arrays: + FREE(comp->role_specific); + FREE(comp->name_specific); + + FREE(comp->name); + + return OMX_ErrorInsufficientResources; +} + +static OMX_ERRORTYPE vid_enc_Constructor(OMX_COMPONENTTYPE *comp, OMX_STRING name) +{ + vid_enc_PrivateType *priv; + omx_base_video_PortType *port; + struct pipe_screen *screen; + OMX_ERRORTYPE r; + int i; + + assert(!comp->pComponentPrivate); + + priv = comp->pComponentPrivate = CALLOC(1, sizeof(vid_enc_PrivateType)); + if (!priv) + return OMX_ErrorInsufficientResources; + + r = omx_base_filter_Constructor(comp, name); + if (r) + return r; + + priv->BufferMgmtCallback = vid_enc_BufferEncoded; + priv->messageHandler = vid_enc_MessageHandler; + priv->destructor = vid_enc_Destructor; + + comp->SetParameter = vid_enc_SetParameter; + comp->GetParameter = vid_enc_GetParameter; + comp->GetConfig = vid_enc_GetConfig; + comp->SetConfig = vid_enc_SetConfig; + + priv->screen = omx_get_screen(); + if (!priv->screen) + return OMX_ErrorInsufficientResources; + + screen = priv->screen->pscreen; + if (!screen->get_video_param(screen, PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH, + PIPE_VIDEO_ENTRYPOINT_ENCODE, PIPE_VIDEO_CAP_SUPPORTED)) + return OMX_ErrorBadParameter; + + priv->s_pipe = screen->context_create(screen, NULL, 0); + if (!priv->s_pipe) + return OMX_ErrorInsufficientResources; + + if (!vl_compositor_init(&priv->compositor, priv->s_pipe)) { + priv->s_pipe->destroy(priv->s_pipe); + priv->s_pipe = NULL; + return OMX_ErrorInsufficientResources; + } + + if (!vl_compositor_init_state(&priv->cstate, priv->s_pipe)) { + vl_compositor_cleanup(&priv->compositor); + priv->s_pipe->destroy(priv->s_pipe); + priv->s_pipe = NULL; + return OMX_ErrorInsufficientResources; + } + + priv->t_pipe = screen->context_create(screen, NULL, 0); + if (!priv->t_pipe) + return OMX_ErrorInsufficientResources; + + priv->sPortTypesParam[OMX_PortDomainVideo].nStartPortNumber = 0; + priv->sPortTypesParam[OMX_PortDomainVideo].nPorts = 2; + priv->ports = CALLOC(2, sizeof(omx_base_PortType *)); + if (!priv->ports) + return OMX_ErrorInsufficientResources; + + for (i = 0; i < 2; ++i) { + priv->ports[i] = CALLOC(1, sizeof(omx_base_video_PortType)); + if (!priv->ports[i]) + return OMX_ErrorInsufficientResources; + + base_video_port_Constructor(comp, &priv->ports[i], i, i == 0); + } + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; + port->sPortParam.format.video.nFrameWidth = 176; + port->sPortParam.format.video.nFrameHeight = 144; + port->sPortParam.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + port->sVideoParam.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + port->sPortParam.nBufferCountActual = 8; + port->sPortParam.nBufferCountMin = 4; + + port->Port_SendBufferFunction = vid_enc_EncodeFrame; + port->Port_AllocateBuffer = vid_enc_AllocateInBuffer; + port->Port_UseBuffer = vid_enc_UseInBuffer; + port->Port_FreeBuffer = vid_enc_FreeInBuffer; + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; + strcpy(port->sPortParam.format.video.cMIMEType,"video/H264"); + port->sPortParam.format.video.nFrameWidth = 176; + port->sPortParam.format.video.nFrameHeight = 144; + port->sPortParam.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC; + port->sVideoParam.eCompressionFormat = OMX_VIDEO_CodingAVC; + + port->Port_AllocateBuffer = vid_enc_AllocateOutBuffer; + port->Port_FreeBuffer = vid_enc_FreeOutBuffer; + + priv->bitrate.eControlRate = OMX_Video_ControlRateDisable; + priv->bitrate.nTargetBitrate = 0; + + priv->quant.nQpI = OMX_VID_ENC_QUANT_I_FRAMES_DEFAULT; + priv->quant.nQpP = OMX_VID_ENC_QUANT_P_FRAMES_DEFAULT; + priv->quant.nQpB = OMX_VID_ENC_QUANT_B_FRAMES_DEFAULT; + + priv->profile_level.eProfile = OMX_VIDEO_AVCProfileBaseline; + priv->profile_level.eLevel = OMX_VIDEO_AVCLevel51; + + priv->force_pic_type.IntraRefreshVOP = OMX_FALSE; + priv->frame_num = 0; + priv->pic_order_cnt = 0; + priv->restricted_b_frames = debug_get_bool_option("OMX_USE_RESTRICTED_B_FRAMES", FALSE); + + priv->scale.xWidth = OMX_VID_ENC_SCALING_WIDTH_DEFAULT; + priv->scale.xHeight = OMX_VID_ENC_SCALING_WIDTH_DEFAULT; + + LIST_INITHEAD(&priv->free_tasks); + LIST_INITHEAD(&priv->used_tasks); + LIST_INITHEAD(&priv->b_frames); + LIST_INITHEAD(&priv->stacked_tasks); + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_enc_Destructor(OMX_COMPONENTTYPE *comp) +{ + vid_enc_PrivateType* priv = comp->pComponentPrivate; + int i; + + enc_ReleaseTasks(&priv->free_tasks); + enc_ReleaseTasks(&priv->used_tasks); + enc_ReleaseTasks(&priv->b_frames); + enc_ReleaseTasks(&priv->stacked_tasks); + + if (priv->ports) { + for (i = 0; i < priv->sPortTypesParam[OMX_PortDomainVideo].nPorts; ++i) { + if(priv->ports[i]) + priv->ports[i]->PortDestructor(priv->ports[i]); + } + FREE(priv->ports); + priv->ports=NULL; + } + + for (i = 0; i < OMX_VID_ENC_NUM_SCALING_BUFFERS; ++i) + if (priv->scale_buffer[i]) + priv->scale_buffer[i]->destroy(priv->scale_buffer[i]); + + if (priv->s_pipe) { + vl_compositor_cleanup_state(&priv->cstate); + vl_compositor_cleanup(&priv->compositor); + priv->s_pipe->destroy(priv->s_pipe); + } + + if (priv->t_pipe) + priv->t_pipe->destroy(priv->t_pipe); + + if (priv->screen) + omx_put_screen(); + + return omx_workaround_Destructor(comp); +} + +static OMX_ERRORTYPE enc_AllocateBackTexture(omx_base_PortType *port, + struct pipe_resource **resource, + struct pipe_transfer **transfer, + OMX_U8 **map) +{ + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + struct pipe_resource buf_templ; + struct pipe_box box = {}; + OMX_U8 *ptr; + + memset(&buf_templ, 0, sizeof buf_templ); + buf_templ.target = PIPE_TEXTURE_2D; + buf_templ.format = PIPE_FORMAT_I8_UNORM; + buf_templ.bind = PIPE_BIND_LINEAR; + buf_templ.usage = PIPE_USAGE_STAGING; + buf_templ.flags = 0; + buf_templ.width0 = port->sPortParam.format.video.nFrameWidth; + buf_templ.height0 = port->sPortParam.format.video.nFrameHeight * 3 / 2; + buf_templ.depth0 = 1; + buf_templ.array_size = 1; + + *resource = priv->s_pipe->screen->resource_create(priv->s_pipe->screen, &buf_templ); + if (!*resource) + return OMX_ErrorInsufficientResources; + + box.width = (*resource)->width0; + box.height = (*resource)->height0; + box.depth = (*resource)->depth0; + ptr = priv->s_pipe->transfer_map(priv->s_pipe, *resource, 0, PIPE_TRANSFER_WRITE, &box, transfer); + if (map) + *map = ptr; + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_enc_SetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param) +{ + OMX_COMPONENTTYPE *comp = handle; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + OMX_ERRORTYPE r; + + if (!param) + return OMX_ErrorBadParameter; + + switch(idx) { + case OMX_IndexParamPortDefinition: { + OMX_PARAM_PORTDEFINITIONTYPE *def = param; + + r = omx_base_component_SetParameter(handle, idx, param); + if (r) + return r; + + if (def->nPortIndex == OMX_BASE_FILTER_INPUTPORT_INDEX) { + omx_base_video_PortType *port; + unsigned framesize; + struct pipe_resource *resource; + struct pipe_transfer *transfer; + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; + enc_AllocateBackTexture(priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX], + &resource, &transfer, NULL); + port->sPortParam.format.video.nStride = transfer->stride; + pipe_transfer_unmap(priv->s_pipe, transfer); + pipe_resource_reference(&resource, NULL); + + framesize = port->sPortParam.format.video.nStride * + port->sPortParam.format.video.nFrameHeight; + port->sPortParam.format.video.nSliceHeight = port->sPortParam.format.video.nFrameHeight; + port->sPortParam.nBufferSize = framesize * 3 / 2; + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]; + port->sPortParam.nBufferSize = framesize * 512 / (16*16); + + priv->frame_rate = def->format.video.xFramerate; + + priv->callbacks->EventHandler(comp, priv->callbackData, OMX_EventPortSettingsChanged, + OMX_BASE_FILTER_OUTPUTPORT_INDEX, 0, NULL); + } + break; + } + case OMX_IndexParamStandardComponentRole: { + OMX_PARAM_COMPONENTROLETYPE *role = param; + + r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (r) + return r; + + if (strcmp((char *)role->cRole, OMX_VID_ENC_AVC_ROLE)) { + return OMX_ErrorBadParameter; + } + + break; + } + case OMX_IndexParamVideoBitrate: { + OMX_VIDEO_PARAM_BITRATETYPE *bitrate = param; + + r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_BITRATETYPE)); + if (r) + return r; + + priv->bitrate = *bitrate; + + break; + } + case OMX_IndexParamVideoQuantization: { + OMX_VIDEO_PARAM_QUANTIZATIONTYPE *quant = param; + + r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_QUANTIZATIONTYPE)); + if (r) + return r; + + priv->quant = *quant; + + break; + } + case OMX_IndexParamVideoProfileLevelCurrent: { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *profile_level = param; + + r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (r) + return r; + + priv->profile_level = *profile_level; + + break; + } + default: + return omx_base_component_SetParameter(handle, idx, param); + } + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_enc_GetParameter(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR param) +{ + OMX_COMPONENTTYPE *comp = handle; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + OMX_ERRORTYPE r; + + if (!param) + return OMX_ErrorBadParameter; + + switch(idx) { + case OMX_IndexParamStandardComponentRole: { + OMX_PARAM_COMPONENTROLETYPE *role = param; + + r = checkHeader(param, sizeof(OMX_PARAM_COMPONENTROLETYPE)); + if (r) + return r; + + strcpy((char *)role->cRole, OMX_VID_ENC_AVC_ROLE); + break; + } + case OMX_IndexParamVideoInit: + r = checkHeader(param, sizeof(OMX_PORT_PARAM_TYPE)); + if (r) + return r; + + memcpy(param, &priv->sPortTypesParam[OMX_PortDomainVideo], sizeof(OMX_PORT_PARAM_TYPE)); + break; + + case OMX_IndexParamVideoPortFormat: { + OMX_VIDEO_PARAM_PORTFORMATTYPE *format = param; + omx_base_video_PortType *port; + + r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + if (r) + return r; + + if (format->nPortIndex > 1) + return OMX_ErrorBadPortIndex; + if (format->nIndex >= 1) + return OMX_ErrorNoMore; + + port = (omx_base_video_PortType *)priv->ports[format->nPortIndex]; + memcpy(format, &port->sVideoParam, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); + break; + } + case OMX_IndexParamVideoBitrate: { + OMX_VIDEO_PARAM_BITRATETYPE *bitrate = param; + + r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_BITRATETYPE)); + if (r) + return r; + + bitrate->eControlRate = priv->bitrate.eControlRate; + bitrate->nTargetBitrate = priv->bitrate.nTargetBitrate; + + break; + } + case OMX_IndexParamVideoQuantization: { + OMX_VIDEO_PARAM_QUANTIZATIONTYPE *quant = param; + + r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_QUANTIZATIONTYPE)); + if (r) + return r; + + quant->nQpI = priv->quant.nQpI; + quant->nQpP = priv->quant.nQpP; + quant->nQpB = priv->quant.nQpB; + + break; + } + case OMX_IndexParamVideoProfileLevelCurrent: { + OMX_VIDEO_PARAM_PROFILELEVELTYPE *profile_level = param; + + r = checkHeader(param, sizeof(OMX_VIDEO_PARAM_PROFILELEVELTYPE)); + if (r) + return r; + + profile_level->eProfile = priv->profile_level.eProfile; + profile_level->eLevel = priv->profile_level.eLevel; + + break; + } + default: + return omx_base_component_GetParameter(handle, idx, param); + } + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_enc_SetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config) +{ + OMX_COMPONENTTYPE *comp = handle; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + OMX_ERRORTYPE r; + int i; + + if (!config) + return OMX_ErrorBadParameter; + + switch(idx) { + case OMX_IndexConfigVideoIntraVOPRefresh: { + OMX_CONFIG_INTRAREFRESHVOPTYPE *type = config; + + r = checkHeader(config, sizeof(OMX_CONFIG_INTRAREFRESHVOPTYPE)); + if (r) + return r; + + priv->force_pic_type = *type; + + break; + } + case OMX_IndexConfigCommonScale: { + OMX_CONFIG_SCALEFACTORTYPE *scale = config; + + r = checkHeader(config, sizeof(OMX_CONFIG_SCALEFACTORTYPE)); + if (r) + return r; + + if (scale->xWidth < 176 || scale->xHeight < 144) + return OMX_ErrorBadParameter; + + for (i = 0; i < OMX_VID_ENC_NUM_SCALING_BUFFERS; ++i) { + if (priv->scale_buffer[i]) { + priv->scale_buffer[i]->destroy(priv->scale_buffer[i]); + priv->scale_buffer[i] = NULL; + } + } + + priv->scale = *scale; + if (priv->scale.xWidth != 0xffffffff && priv->scale.xHeight != 0xffffffff) { + struct pipe_video_buffer templat = {}; + + templat.buffer_format = PIPE_FORMAT_NV12; + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + templat.width = priv->scale.xWidth; + templat.height = priv->scale.xHeight; + templat.interlaced = false; + for (i = 0; i < OMX_VID_ENC_NUM_SCALING_BUFFERS; ++i) { + priv->scale_buffer[i] = priv->s_pipe->create_video_buffer(priv->s_pipe, &templat); + if (!priv->scale_buffer[i]) + return OMX_ErrorInsufficientResources; + } + } + + break; + } + default: + return omx_base_component_SetConfig(handle, idx, config); + } + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_enc_GetConfig(OMX_HANDLETYPE handle, OMX_INDEXTYPE idx, OMX_PTR config) +{ + OMX_COMPONENTTYPE *comp = handle; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + OMX_ERRORTYPE r; + + if (!config) + return OMX_ErrorBadParameter; + + switch(idx) { + case OMX_IndexConfigCommonScale: { + OMX_CONFIG_SCALEFACTORTYPE *scale = config; + + r = checkHeader(config, sizeof(OMX_CONFIG_SCALEFACTORTYPE)); + if (r) + return r; + + scale->xWidth = priv->scale.xWidth; + scale->xHeight = priv->scale.xHeight; + + break; + } + default: + return omx_base_component_GetConfig(handle, idx, config); + } + + return OMX_ErrorNone; +} + +static enum pipe_video_profile enc_TranslateOMXProfileToPipe(unsigned omx_profile) +{ + switch (omx_profile) { + case OMX_VIDEO_AVCProfileBaseline: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE; + case OMX_VIDEO_AVCProfileMain: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN; + case OMX_VIDEO_AVCProfileExtended: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_EXTENDED; + case OMX_VIDEO_AVCProfileHigh: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; + case OMX_VIDEO_AVCProfileHigh10: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH10; + case OMX_VIDEO_AVCProfileHigh422: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH422; + case OMX_VIDEO_AVCProfileHigh444: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH444; + default: + return PIPE_VIDEO_PROFILE_UNKNOWN; + } +} + +static unsigned enc_TranslateOMXLevelToPipe(unsigned omx_level) +{ + switch (omx_level) { + case OMX_VIDEO_AVCLevel1: + case OMX_VIDEO_AVCLevel1b: + return 10; + case OMX_VIDEO_AVCLevel11: + return 11; + case OMX_VIDEO_AVCLevel12: + return 12; + case OMX_VIDEO_AVCLevel13: + return 13; + case OMX_VIDEO_AVCLevel2: + return 20; + case OMX_VIDEO_AVCLevel21: + return 21; + case OMX_VIDEO_AVCLevel22: + return 22; + case OMX_VIDEO_AVCLevel3: + return 30; + case OMX_VIDEO_AVCLevel31: + return 31; + case OMX_VIDEO_AVCLevel32: + return 32; + case OMX_VIDEO_AVCLevel4: + return 40; + case OMX_VIDEO_AVCLevel41: + return 41; + default: + case OMX_VIDEO_AVCLevel42: + return 42; + case OMX_VIDEO_AVCLevel5: + return 50; + case OMX_VIDEO_AVCLevel51: + return 51; + } +} + +static OMX_ERRORTYPE vid_enc_MessageHandler(OMX_COMPONENTTYPE* comp, internalRequestMessageType *msg) +{ + vid_enc_PrivateType* priv = comp->pComponentPrivate; + + if (msg->messageType == OMX_CommandStateSet) { + if ((msg->messageParam == OMX_StateIdle ) && (priv->state == OMX_StateLoaded)) { + + struct pipe_video_codec templat = {}; + omx_base_video_PortType *port; + + port = (omx_base_video_PortType *)priv->ports[OMX_BASE_FILTER_INPUTPORT_INDEX]; + + templat.profile = enc_TranslateOMXProfileToPipe(priv->profile_level.eProfile); + templat.level = enc_TranslateOMXLevelToPipe(priv->profile_level.eLevel); + templat.entrypoint = PIPE_VIDEO_ENTRYPOINT_ENCODE; + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + templat.width = priv->scale_buffer[priv->current_scale_buffer] ? + priv->scale.xWidth : port->sPortParam.format.video.nFrameWidth; + templat.height = priv->scale_buffer[priv->current_scale_buffer] ? + priv->scale.xHeight : port->sPortParam.format.video.nFrameHeight; + + if (templat.profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE) { + struct pipe_screen *screen = priv->screen->pscreen; + templat.max_references = 1; + priv->stacked_frames_num = + screen->get_video_param(screen, + PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH, + PIPE_VIDEO_ENTRYPOINT_ENCODE, + PIPE_VIDEO_CAP_STACKED_FRAMES); + } else { + templat.max_references = OMX_VID_ENC_P_PERIOD_DEFAULT; + priv->stacked_frames_num = 1; + } + priv->codec = priv->s_pipe->create_video_codec(priv->s_pipe, &templat); + + } else if ((msg->messageParam == OMX_StateLoaded) && (priv->state == OMX_StateIdle)) { + if (priv->codec) { + priv->codec->destroy(priv->codec); + priv->codec = NULL; + } + } + } + + return omx_base_component_MessageHandler(comp, msg); +} + +static OMX_ERRORTYPE vid_enc_AllocateInBuffer(omx_base_PortType *port, OMX_INOUT OMX_BUFFERHEADERTYPE **buf, + OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size) +{ + struct input_buf_private *inp; + OMX_ERRORTYPE r; + + r = base_port_AllocateBuffer(port, buf, idx, private, size); + if (r) + return r; + + inp = (*buf)->pInputPortPrivate = CALLOC_STRUCT(input_buf_private); + if (!inp) { + base_port_FreeBuffer(port, idx, *buf); + return OMX_ErrorInsufficientResources; + } + + LIST_INITHEAD(&inp->tasks); + + FREE((*buf)->pBuffer); + r = enc_AllocateBackTexture(port, &inp->resource, &inp->transfer, &(*buf)->pBuffer); + if (r) { + FREE(inp); + base_port_FreeBuffer(port, idx, *buf); + return r; + } + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_enc_UseInBuffer(omx_base_PortType *port, OMX_BUFFERHEADERTYPE **buf, OMX_U32 idx, + OMX_PTR private, OMX_U32 size, OMX_U8 *mem) +{ + struct input_buf_private *inp; + OMX_ERRORTYPE r; + + r = base_port_UseBuffer(port, buf, idx, private, size, mem); + if (r) + return r; + + inp = (*buf)->pInputPortPrivate = CALLOC_STRUCT(input_buf_private); + if (!inp) { + base_port_FreeBuffer(port, idx, *buf); + return OMX_ErrorInsufficientResources; + } + + LIST_INITHEAD(&inp->tasks); + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_enc_FreeInBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf) +{ + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + struct input_buf_private *inp = buf->pInputPortPrivate; + + if (inp) { + enc_ReleaseTasks(&inp->tasks); + if (inp->transfer) + pipe_transfer_unmap(priv->s_pipe, inp->transfer); + pipe_resource_reference(&inp->resource, NULL); + FREE(inp); + } + buf->pBuffer = NULL; + + return base_port_FreeBuffer(port, idx, buf); +} + +static OMX_ERRORTYPE vid_enc_AllocateOutBuffer(omx_base_PortType *port, OMX_INOUT OMX_BUFFERHEADERTYPE **buf, + OMX_IN OMX_U32 idx, OMX_IN OMX_PTR private, OMX_IN OMX_U32 size) +{ + OMX_ERRORTYPE r; + + r = base_port_AllocateBuffer(port, buf, idx, private, size); + if (r) + return r; + + FREE((*buf)->pBuffer); + (*buf)->pBuffer = NULL; + (*buf)->pOutputPortPrivate = CALLOC(1, sizeof(struct output_buf_private)); + if (!(*buf)->pOutputPortPrivate) { + base_port_FreeBuffer(port, idx, *buf); + return OMX_ErrorInsufficientResources; + } + + return OMX_ErrorNone; +} + +static OMX_ERRORTYPE vid_enc_FreeOutBuffer(omx_base_PortType *port, OMX_U32 idx, OMX_BUFFERHEADERTYPE *buf) +{ + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + + if (buf->pOutputPortPrivate) { + struct output_buf_private *outp = buf->pOutputPortPrivate; + if (outp->transfer) + pipe_transfer_unmap(priv->t_pipe, outp->transfer); + pipe_resource_reference(&outp->bitstream, NULL); + FREE(outp); + buf->pOutputPortPrivate = NULL; + } + buf->pBuffer = NULL; + + return base_port_FreeBuffer(port, idx, buf); +} + +static struct encode_task *enc_NeedTask(omx_base_PortType *port) +{ + OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + + struct pipe_video_buffer templat = {}; + struct encode_task *task; + + if (!LIST_IS_EMPTY(&priv->free_tasks)) { + task = LIST_ENTRY(struct encode_task, priv->free_tasks.next, list); + LIST_DEL(&task->list); + return task; + } + + /* allocate a new one */ + task = CALLOC_STRUCT(encode_task); + if (!task) + return NULL; + + templat.buffer_format = PIPE_FORMAT_NV12; + templat.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; + templat.width = def->nFrameWidth; + templat.height = def->nFrameHeight; + templat.interlaced = false; + + task->buf = priv->s_pipe->create_video_buffer(priv->s_pipe, &templat); + if (!task->buf) { + FREE(task); + return NULL; + } + + return task; +} + +static void enc_MoveTasks(struct list_head *from, struct list_head *to) +{ + to->prev->next = from->next; + from->next->prev = to->prev; + from->prev->next = to; + to->prev = from->prev; + LIST_INITHEAD(from); +} + +static void enc_ReleaseTasks(struct list_head *head) +{ + struct encode_task *i, *next; + + if (!head || !head->next) + return; + + LIST_FOR_EACH_ENTRY_SAFE(i, next, head, list) { + pipe_resource_reference(&i->bitstream, NULL); + i->buf->destroy(i->buf); + FREE(i); + } +} + +static OMX_ERRORTYPE enc_LoadImage(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf, + struct pipe_video_buffer *vbuf) +{ + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; + struct pipe_box box = {}; + struct input_buf_private *inp = buf->pInputPortPrivate; + + if (!inp->resource) { + struct pipe_sampler_view **views; + void *ptr; + + views = vbuf->get_sampler_view_planes(vbuf); + if (!views) + return OMX_ErrorInsufficientResources; + + ptr = buf->pBuffer; + box.width = def->nFrameWidth; + box.height = def->nFrameHeight; + box.depth = 1; + priv->s_pipe->texture_subdata(priv->s_pipe, views[0]->texture, 0, + PIPE_TRANSFER_WRITE, &box, + ptr, def->nStride, 0); + ptr = ((uint8_t*)buf->pBuffer) + (def->nStride * box.height); + box.width = def->nFrameWidth / 2; + box.height = def->nFrameHeight / 2; + box.depth = 1; + priv->s_pipe->texture_subdata(priv->s_pipe, views[1]->texture, 0, + PIPE_TRANSFER_WRITE, &box, + ptr, def->nStride, 0); + } else { + struct pipe_blit_info blit; + struct vl_video_buffer *dst_buf = (struct vl_video_buffer *)vbuf; + + pipe_transfer_unmap(priv->s_pipe, inp->transfer); + + box.width = def->nFrameWidth; + box.height = def->nFrameHeight; + box.depth = 1; + + priv->s_pipe->resource_copy_region(priv->s_pipe, + dst_buf->resources[0], + 0, 0, 0, 0, inp->resource, 0, &box); + + memset(&blit, 0, sizeof(blit)); + blit.src.resource = inp->resource; + blit.src.format = inp->resource->format; + + blit.src.box.x = 0; + blit.src.box.y = def->nFrameHeight; + blit.src.box.width = def->nFrameWidth; + blit.src.box.height = def->nFrameHeight / 2 ; + blit.src.box.depth = 1; + + blit.dst.resource = dst_buf->resources[1]; + blit.dst.format = blit.dst.resource->format; + + blit.dst.box.width = def->nFrameWidth / 2; + blit.dst.box.height = def->nFrameHeight / 2; + blit.dst.box.depth = 1; + blit.filter = PIPE_TEX_FILTER_NEAREST; + + blit.mask = PIPE_MASK_G; + priv->s_pipe->blit(priv->s_pipe, &blit); + + blit.src.box.x = 1; + blit.mask = PIPE_MASK_R; + priv->s_pipe->blit(priv->s_pipe, &blit); + priv->s_pipe->flush(priv->s_pipe, NULL, 0); + + box.width = inp->resource->width0; + box.height = inp->resource->height0; + box.depth = inp->resource->depth0; + buf->pBuffer = priv->s_pipe->transfer_map(priv->s_pipe, inp->resource, 0, + PIPE_TRANSFER_WRITE, &box, + &inp->transfer); + } + + return OMX_ErrorNone; +} + +static void enc_ScaleInput(omx_base_PortType *port, struct pipe_video_buffer **vbuf, unsigned *size) +{ + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + OMX_VIDEO_PORTDEFINITIONTYPE *def = &port->sPortParam.format.video; + struct pipe_video_buffer *src_buf = *vbuf; + struct vl_compositor *compositor = &priv->compositor; + struct vl_compositor_state *s = &priv->cstate; + struct pipe_sampler_view **views; + struct pipe_surface **dst_surface; + unsigned i; + + if (!priv->scale_buffer[priv->current_scale_buffer]) + return; + + views = src_buf->get_sampler_view_planes(src_buf); + dst_surface = priv->scale_buffer[priv->current_scale_buffer]->get_surfaces + (priv->scale_buffer[priv->current_scale_buffer]); + vl_compositor_clear_layers(s); + + for (i = 0; i < VL_MAX_SURFACES; ++i) { + struct u_rect src_rect; + if (!views[i] || !dst_surface[i]) + continue; + src_rect.x0 = 0; + src_rect.y0 = 0; + src_rect.x1 = def->nFrameWidth; + src_rect.y1 = def->nFrameHeight; + if (i > 0) { + src_rect.x1 /= 2; + src_rect.y1 /= 2; + } + vl_compositor_set_rgba_layer(s, compositor, 0, views[i], &src_rect, NULL, NULL); + vl_compositor_render(s, compositor, dst_surface[i], NULL, false); + } + *size = priv->scale.xWidth * priv->scale.xHeight * 2; + *vbuf = priv->scale_buffer[priv->current_scale_buffer++]; + priv->current_scale_buffer %= OMX_VID_ENC_NUM_SCALING_BUFFERS; +} + +static void enc_GetPictureParamPreset(struct pipe_h264_enc_picture_desc *picture) +{ + picture->motion_est.enc_disable_sub_mode = 0x000000fe; + picture->motion_est.enc_ime2_search_range_x = 0x00000001; + picture->motion_est.enc_ime2_search_range_y = 0x00000001; + picture->pic_ctrl.enc_constraint_set_flags = 0x00000040; +} + +static void enc_ControlPicture(omx_base_PortType *port, struct pipe_h264_enc_picture_desc *picture) +{ + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + struct pipe_h264_enc_rate_control *rate_ctrl = &picture->rate_ctrl; + + switch (priv->bitrate.eControlRate) { + case OMX_Video_ControlRateVariable: + rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_VARIABLE; + break; + case OMX_Video_ControlRateConstant: + rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_CONSTANT; + break; + case OMX_Video_ControlRateVariableSkipFrames: + rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_VARIABLE_SKIP; + break; + case OMX_Video_ControlRateConstantSkipFrames: + rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_CONSTANT_SKIP; + break; + default: + rate_ctrl->rate_ctrl_method = PIPE_H264_ENC_RATE_CONTROL_METHOD_DISABLE; + break; + } + + rate_ctrl->frame_rate_den = OMX_VID_ENC_CONTROL_FRAME_RATE_DEN_DEFAULT; + rate_ctrl->frame_rate_num = ((priv->frame_rate) >> 16) * rate_ctrl->frame_rate_den; + + if (rate_ctrl->rate_ctrl_method != PIPE_H264_ENC_RATE_CONTROL_METHOD_DISABLE) { + if (priv->bitrate.nTargetBitrate < OMX_VID_ENC_BITRATE_MIN) + rate_ctrl->target_bitrate = OMX_VID_ENC_BITRATE_MIN; + else if (priv->bitrate.nTargetBitrate < OMX_VID_ENC_BITRATE_MAX) + rate_ctrl->target_bitrate = priv->bitrate.nTargetBitrate; + else + rate_ctrl->target_bitrate = OMX_VID_ENC_BITRATE_MAX; + rate_ctrl->peak_bitrate = rate_ctrl->target_bitrate; + if (rate_ctrl->target_bitrate < OMX_VID_ENC_BITRATE_MEDIAN) + rate_ctrl->vbv_buffer_size = MIN2((rate_ctrl->target_bitrate * 2.75), OMX_VID_ENC_BITRATE_MEDIAN); + else + rate_ctrl->vbv_buffer_size = rate_ctrl->target_bitrate; + + if (rate_ctrl->frame_rate_num) { + unsigned long long t = rate_ctrl->target_bitrate; + t *= rate_ctrl->frame_rate_den; + rate_ctrl->target_bits_picture = t / rate_ctrl->frame_rate_num; + } else { + rate_ctrl->target_bits_picture = rate_ctrl->target_bitrate; + } + rate_ctrl->peak_bits_picture_integer = rate_ctrl->target_bits_picture; + rate_ctrl->peak_bits_picture_fraction = 0; + } + + picture->quant_i_frames = priv->quant.nQpI; + picture->quant_p_frames = priv->quant.nQpP; + picture->quant_b_frames = priv->quant.nQpB; + + picture->frame_num = priv->frame_num; + picture->ref_idx_l0 = priv->ref_idx_l0; + picture->ref_idx_l1 = priv->ref_idx_l1; + picture->enable_vui = (picture->rate_ctrl.frame_rate_num != 0); + enc_GetPictureParamPreset(picture); +} + +static void enc_HandleTask(omx_base_PortType *port, struct encode_task *task, + enum pipe_h264_enc_picture_type picture_type) +{ + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + unsigned size = priv->ports[OMX_BASE_FILTER_OUTPUTPORT_INDEX]->sPortParam.nBufferSize; + struct pipe_video_buffer *vbuf = task->buf; + struct pipe_h264_enc_picture_desc picture = {}; + + /* -------------- scale input image --------- */ + enc_ScaleInput(port, &vbuf, &size); + priv->s_pipe->flush(priv->s_pipe, NULL, 0); + + /* -------------- allocate output buffer --------- */ + task->bitstream = pipe_buffer_create(priv->s_pipe->screen, + PIPE_BIND_VERTEX_BUFFER, + PIPE_USAGE_STAGING, /* map for read */ + size); + + picture.picture_type = picture_type; + picture.pic_order_cnt = task->pic_order_cnt; + if (priv->restricted_b_frames && picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) + picture.not_referenced = true; + enc_ControlPicture(port, &picture); + + /* -------------- encode frame --------- */ + priv->codec->begin_frame(priv->codec, vbuf, &picture.base); + priv->codec->encode_bitstream(priv->codec, vbuf, task->bitstream, &task->feedback); + priv->codec->end_frame(priv->codec, vbuf, &picture.base); +} + +static void enc_ClearBframes(omx_base_PortType *port, struct input_buf_private *inp) +{ + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + struct encode_task *task; + + if (LIST_IS_EMPTY(&priv->b_frames)) + return; + + task = LIST_ENTRY(struct encode_task, priv->b_frames.prev, list); + LIST_DEL(&task->list); + + /* promote last from to P frame */ + priv->ref_idx_l0 = priv->ref_idx_l1; + enc_HandleTask(port, task, PIPE_H264_ENC_PICTURE_TYPE_P); + LIST_ADDTAIL(&task->list, &inp->tasks); + priv->ref_idx_l1 = priv->frame_num++; + + /* handle B frames */ + LIST_FOR_EACH_ENTRY(task, &priv->b_frames, list) { + enc_HandleTask(port, task, PIPE_H264_ENC_PICTURE_TYPE_B); + if (!priv->restricted_b_frames) + priv->ref_idx_l0 = priv->frame_num; + priv->frame_num++; + } + + enc_MoveTasks(&priv->b_frames, &inp->tasks); +} + +static OMX_ERRORTYPE vid_enc_EncodeFrame(omx_base_PortType *port, OMX_BUFFERHEADERTYPE *buf) +{ + OMX_COMPONENTTYPE* comp = port->standCompContainer; + vid_enc_PrivateType *priv = comp->pComponentPrivate; + struct input_buf_private *inp = buf->pInputPortPrivate; + enum pipe_h264_enc_picture_type picture_type; + struct encode_task *task; + unsigned stacked_num = 0; + OMX_ERRORTYPE err; + + enc_MoveTasks(&inp->tasks, &priv->free_tasks); + task = enc_NeedTask(port); + if (!task) + return OMX_ErrorInsufficientResources; + + if (buf->nFilledLen == 0) { + if (buf->nFlags & OMX_BUFFERFLAG_EOS) { + buf->nFilledLen = buf->nAllocLen; + enc_ClearBframes(port, inp); + enc_MoveTasks(&priv->stacked_tasks, &inp->tasks); + priv->codec->flush(priv->codec); + } + return base_port_SendBufferFunction(port, buf); + } + + if (buf->pOutputPortPrivate) { + struct pipe_video_buffer *vbuf = buf->pOutputPortPrivate; + buf->pOutputPortPrivate = task->buf; + task->buf = vbuf; + } else { + /* ------- load input image into video buffer ---- */ + err = enc_LoadImage(port, buf, task->buf); + if (err != OMX_ErrorNone) { + FREE(task); + return err; + } + } + + /* -------------- determine picture type --------- */ + if (!(priv->pic_order_cnt % OMX_VID_ENC_IDR_PERIOD_DEFAULT) || + priv->force_pic_type.IntraRefreshVOP) { + enc_ClearBframes(port, inp); + picture_type = PIPE_H264_ENC_PICTURE_TYPE_IDR; + priv->force_pic_type.IntraRefreshVOP = OMX_FALSE; + priv->frame_num = 0; + } else if (priv->codec->profile == PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE || + !(priv->pic_order_cnt % OMX_VID_ENC_P_PERIOD_DEFAULT) || + (buf->nFlags & OMX_BUFFERFLAG_EOS)) { + picture_type = PIPE_H264_ENC_PICTURE_TYPE_P; + } else { + picture_type = PIPE_H264_ENC_PICTURE_TYPE_B; + } + + task->pic_order_cnt = priv->pic_order_cnt++; + + if (picture_type == PIPE_H264_ENC_PICTURE_TYPE_B) { + /* put frame at the tail of the queue */ + LIST_ADDTAIL(&task->list, &priv->b_frames); + } else { + /* handle I or P frame */ + priv->ref_idx_l0 = priv->ref_idx_l1; + enc_HandleTask(port, task, picture_type); + LIST_ADDTAIL(&task->list, &priv->stacked_tasks); + LIST_FOR_EACH_ENTRY(task, &priv->stacked_tasks, list) { + ++stacked_num; + } + if (stacked_num == priv->stacked_frames_num) { + struct encode_task *t; + t = LIST_ENTRY(struct encode_task, priv->stacked_tasks.next, list); + LIST_DEL(&t->list); + LIST_ADDTAIL(&t->list, &inp->tasks); + } + priv->ref_idx_l1 = priv->frame_num++; + + /* handle B frames */ + LIST_FOR_EACH_ENTRY(task, &priv->b_frames, list) { + enc_HandleTask(port, task, PIPE_H264_ENC_PICTURE_TYPE_B); + if (!priv->restricted_b_frames) + priv->ref_idx_l0 = priv->frame_num; + priv->frame_num++; + } + + enc_MoveTasks(&priv->b_frames, &inp->tasks); + } + + if (LIST_IS_EMPTY(&inp->tasks)) + return port->ReturnBufferFunction(port, buf); + else + return base_port_SendBufferFunction(port, buf); +} + +static void vid_enc_BufferEncoded(OMX_COMPONENTTYPE *comp, OMX_BUFFERHEADERTYPE* input, OMX_BUFFERHEADERTYPE* output) +{ + vid_enc_PrivateType *priv = comp->pComponentPrivate; + struct output_buf_private *outp = output->pOutputPortPrivate; + struct input_buf_private *inp = input->pInputPortPrivate; + struct encode_task *task; + struct pipe_box box = {}; + unsigned size; + + if (!inp || LIST_IS_EMPTY(&inp->tasks)) { + input->nFilledLen = 0; /* mark buffer as empty */ + enc_MoveTasks(&priv->used_tasks, &inp->tasks); + return; + } + + task = LIST_ENTRY(struct encode_task, inp->tasks.next, list); + LIST_DEL(&task->list); + LIST_ADDTAIL(&task->list, &priv->used_tasks); + + if (!task->bitstream) + return; + + /* ------------- map result buffer ----------------- */ + + if (outp->transfer) + pipe_transfer_unmap(priv->t_pipe, outp->transfer); + + pipe_resource_reference(&outp->bitstream, task->bitstream); + pipe_resource_reference(&task->bitstream, NULL); + + box.width = outp->bitstream->width0; + box.height = outp->bitstream->height0; + box.depth = outp->bitstream->depth0; + + output->pBuffer = priv->t_pipe->transfer_map(priv->t_pipe, outp->bitstream, 0, + PIPE_TRANSFER_READ_WRITE, + &box, &outp->transfer); + + /* ------------- get size of result ----------------- */ + + priv->codec->get_feedback(priv->codec, task->feedback, &size); + + output->nOffset = 0; + output->nFilledLen = size; /* mark buffer as full */ + + /* all output buffers contain exactly one frame */ + output->nFlags = OMX_BUFFERFLAG_ENDOFFRAME; +} diff --git a/src/gallium/state_trackers/omx_bellagio/vid_enc.h b/src/gallium/state_trackers/omx_bellagio/vid_enc.h new file mode 100644 index 00000000000..a83374450b5 --- /dev/null +++ b/src/gallium/state_trackers/omx_bellagio/vid_enc.h @@ -0,0 +1,96 @@ +/************************************************************************** + * + * Copyright 2013 Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * Authors: + * Christian König + * + */ + +#ifndef OMX_VID_ENC_H +#define OMX_VID_ENC_H + +#include +#include +#include + +#include +#include + +#include "util/list.h" + +#include "vl/vl_defines.h" +#include "vl/vl_compositor.h" + +#define OMX_VID_ENC_BASE_NAME "OMX.mesa.video_encoder" +#define OMX_VID_ENC_AVC_NAME "OMX.mesa.video_encoder.avc" +#define OMX_VID_ENC_AVC_ROLE "video_encoder.avc" + +#define OMX_VID_ENC_BITRATE_MIN 64000 +#define OMX_VID_ENC_BITRATE_MEDIAN 2000000 +#define OMX_VID_ENC_BITRATE_MAX 240000000 +#define OMX_VID_ENC_CONTROL_FRAME_RATE_DEN_DEFAULT 1001 +#define OMX_VID_ENC_QUANT_I_FRAMES_DEFAULT 0x1c +#define OMX_VID_ENC_QUANT_P_FRAMES_DEFAULT 0x1c +#define OMX_VID_ENC_QUANT_B_FRAMES_DEFAULT 0x1c +#define OMX_VID_ENC_SCALING_WIDTH_DEFAULT 0xffffffff +#define OMX_VID_ENC_SCALING_HEIGHT_DEFAULT 0xffffffff +#define OMX_VID_ENC_IDR_PERIOD_DEFAULT 1000 +#define OMX_VID_ENC_P_PERIOD_DEFAULT 3 + +#define OMX_VID_ENC_NUM_SCALING_BUFFERS 4 + +DERIVEDCLASS(vid_enc_PrivateType, omx_base_filter_PrivateType) +#define vid_enc_PrivateType_FIELDS omx_base_filter_PrivateType_FIELDS \ + struct vl_screen *screen; \ + struct pipe_context *s_pipe; \ + struct pipe_context *t_pipe; \ + struct pipe_video_codec *codec; \ + struct list_head free_tasks; \ + struct list_head used_tasks; \ + struct list_head b_frames; \ + struct list_head stacked_tasks; \ + OMX_U32 frame_rate; \ + OMX_U32 frame_num; \ + OMX_U32 pic_order_cnt; \ + OMX_U32 ref_idx_l0, ref_idx_l1; \ + OMX_BOOL restricted_b_frames; \ + OMX_VIDEO_PARAM_BITRATETYPE bitrate; \ + OMX_VIDEO_PARAM_QUANTIZATIONTYPE quant; \ + OMX_VIDEO_PARAM_PROFILELEVELTYPE profile_level; \ + OMX_CONFIG_INTRAREFRESHVOPTYPE force_pic_type; \ + struct vl_compositor compositor; \ + struct vl_compositor_state cstate; \ + struct pipe_video_buffer *scale_buffer[OMX_VID_ENC_NUM_SCALING_BUFFERS]; \ + OMX_CONFIG_SCALEFACTORTYPE scale; \ + OMX_U32 current_scale_buffer; \ + OMX_U32 stacked_frames_num; +ENDCLASS(vid_enc_PrivateType) + +OMX_ERRORTYPE vid_enc_LoaderComponent(stLoaderComponentType *comp); + +#endif diff --git a/src/gallium/targets/omx-bellagio/Makefile.am b/src/gallium/targets/omx-bellagio/Makefile.am new file mode 100644 index 00000000000..4c9a12c3c74 --- /dev/null +++ b/src/gallium/targets/omx-bellagio/Makefile.am @@ -0,0 +1,75 @@ +include $(top_srcdir)/src/gallium/Automake.inc + +AM_CFLAGS = \ + $(GALLIUM_TARGET_CFLAGS) + +omxdir = $(OMX_BELLAGIO_LIB_INSTALL_DIR) +omx_LTLIBRARIES = libomx_mesa.la + +nodist_EXTRA_libomx_mesa_la_SOURCES = dummy.cpp +libomx_mesa_la_SOURCES = + +libomx_mesa_la_LDFLAGS = \ + -shared \ + -module \ + -no-undefined \ + -avoid-version \ + $(GC_SECTIONS) \ + $(LD_NO_UNDEFINED) + +if HAVE_LD_VERSION_SCRIPT +libomx_mesa_la_LDFLAGS += \ + -Wl,--version-script=$(top_srcdir)/src/gallium/targets/omx-bellagio/omx.sym +endif # HAVE_LD_VERSION_SCRIPT + +libomx_mesa_la_LIBADD = \ + $(top_builddir)/src/gallium/state_trackers/omx_bellagio/libomxtracker.la \ + $(top_builddir)/src/gallium/auxiliary/libgalliumvlwinsys.la \ + $(top_builddir)/src/gallium/auxiliary/libgalliumvl.la \ + $(top_builddir)/src/gallium/auxiliary/libgallium.la \ + $(top_builddir)/src/util/libmesautil.la \ + $(OMX_BELLAGIO_LIBS) \ + $(LIBDRM_LIBS) \ + $(GALLIUM_COMMON_LIB_DEPS) + +if HAVE_PLATFORM_X11 +libomx_mesa_la_LIBADD += \ + $(VL_LIBS) \ + $(XCB_DRI3_LIBS) +endif + +EXTRA_libomx_mesa_la_DEPENDENCIES = omx.sym +EXTRA_DIST = omx.sym + +if HAVE_GALLIUM_STATIC_TARGETS + +TARGET_DRIVERS = +TARGET_CPPFLAGS = +TARGET_LIB_DEPS = + + +include $(top_srcdir)/src/gallium/drivers/nouveau/Automake.inc + +include $(top_srcdir)/src/gallium/drivers/r600/Automake.inc +include $(top_srcdir)/src/gallium/drivers/radeonsi/Automake.inc + +libomx_mesa_la_SOURCES += target.c +libomx_mesa_la_CPPFLAGS = $(TARGET_CPPFLAGS) +libomx_mesa_la_LIBADD += \ + $(top_builddir)/src/gallium/auxiliary/pipe-loader/libpipe_loader_static.la \ + $(GALLIUM_PIPE_LOADER_WINSYS_LIBS) \ + $(TARGET_LIB_DEPS) \ + $(TARGET_COMPILER_LIB_DEPS) \ + $(TARGET_RADEON_WINSYS) $(TARGET_RADEON_COMMON) + +else # HAVE_GALLIUM_STATIC_TARGETS + +libomx_mesa_la_LIBADD += \ + $(top_builddir)/src/gallium/auxiliary/pipe-loader/libpipe_loader_dynamic.la + +endif # HAVE_GALLIUM_STATIC_TARGETS + +if HAVE_GALLIUM_LLVM +libomx_mesa_la_LIBADD += $(LLVM_LIBS) +libomx_mesa_la_LDFLAGS += $(LLVM_LDFLAGS) +endif diff --git a/src/gallium/targets/omx-bellagio/omx.sym b/src/gallium/targets/omx-bellagio/omx.sym new file mode 100644 index 00000000000..e8a287600a5 --- /dev/null +++ b/src/gallium/targets/omx-bellagio/omx.sym @@ -0,0 +1,11 @@ +{ + global: + omx_component_library_Setup; + + # Workaround for an LLVM warning with -simplifycfg-sink-common + # due to LLVM being initialized multiple times. + radeon_drm_winsys_create; + amdgpu_winsys_create; + local: + *; +}; diff --git a/src/gallium/targets/omx-bellagio/target.c b/src/gallium/targets/omx-bellagio/target.c new file mode 100644 index 00000000000..308e23bb4a0 --- /dev/null +++ b/src/gallium/targets/omx-bellagio/target.c @@ -0,0 +1,2 @@ +#include "target-helpers/drm_helper.h" +#include "target-helpers/sw_helper.h" diff --git a/src/gallium/targets/omx/Makefile.am b/src/gallium/targets/omx/Makefile.am deleted file mode 100644 index d977255fcfc..00000000000 --- a/src/gallium/targets/omx/Makefile.am +++ /dev/null @@ -1,75 +0,0 @@ -include $(top_srcdir)/src/gallium/Automake.inc - -AM_CFLAGS = \ - $(GALLIUM_TARGET_CFLAGS) - -omxdir = $(OMX_LIB_INSTALL_DIR) -omx_LTLIBRARIES = libomx_mesa.la - -nodist_EXTRA_libomx_mesa_la_SOURCES = dummy.cpp -libomx_mesa_la_SOURCES = - -libomx_mesa_la_LDFLAGS = \ - -shared \ - -module \ - -no-undefined \ - -avoid-version \ - $(GC_SECTIONS) \ - $(LD_NO_UNDEFINED) - -if HAVE_LD_VERSION_SCRIPT -libomx_mesa_la_LDFLAGS += \ - -Wl,--version-script=$(top_srcdir)/src/gallium/targets/omx/omx.sym -endif # HAVE_LD_VERSION_SCRIPT - -libomx_mesa_la_LIBADD = \ - $(top_builddir)/src/gallium/state_trackers/omx/libomxtracker.la \ - $(top_builddir)/src/gallium/auxiliary/libgalliumvlwinsys.la \ - $(top_builddir)/src/gallium/auxiliary/libgalliumvl.la \ - $(top_builddir)/src/gallium/auxiliary/libgallium.la \ - $(top_builddir)/src/util/libmesautil.la \ - $(OMX_LIBS) \ - $(LIBDRM_LIBS) \ - $(GALLIUM_COMMON_LIB_DEPS) - -if HAVE_PLATFORM_X11 -libomx_mesa_la_LIBADD += \ - $(VL_LIBS) \ - $(XCB_DRI3_LIBS) -endif - -EXTRA_libomx_mesa_la_DEPENDENCIES = omx.sym -EXTRA_DIST = omx.sym - -if HAVE_GALLIUM_STATIC_TARGETS - -TARGET_DRIVERS = -TARGET_CPPFLAGS = -TARGET_LIB_DEPS = - - -include $(top_srcdir)/src/gallium/drivers/nouveau/Automake.inc - -include $(top_srcdir)/src/gallium/drivers/r600/Automake.inc -include $(top_srcdir)/src/gallium/drivers/radeonsi/Automake.inc - -libomx_mesa_la_SOURCES += target.c -libomx_mesa_la_CPPFLAGS = $(TARGET_CPPFLAGS) -libomx_mesa_la_LIBADD += \ - $(top_builddir)/src/gallium/auxiliary/pipe-loader/libpipe_loader_static.la \ - $(GALLIUM_PIPE_LOADER_WINSYS_LIBS) \ - $(TARGET_LIB_DEPS) \ - $(TARGET_COMPILER_LIB_DEPS) \ - $(TARGET_RADEON_WINSYS) $(TARGET_RADEON_COMMON) - -else # HAVE_GALLIUM_STATIC_TARGETS - -libomx_mesa_la_LIBADD += \ - $(top_builddir)/src/gallium/auxiliary/pipe-loader/libpipe_loader_dynamic.la - -endif # HAVE_GALLIUM_STATIC_TARGETS - -if HAVE_GALLIUM_LLVM -libomx_mesa_la_LIBADD += $(LLVM_LIBS) -libomx_mesa_la_LDFLAGS += $(LLVM_LDFLAGS) -endif diff --git a/src/gallium/targets/omx/omx.sym b/src/gallium/targets/omx/omx.sym deleted file mode 100644 index e8a287600a5..00000000000 --- a/src/gallium/targets/omx/omx.sym +++ /dev/null @@ -1,11 +0,0 @@ -{ - global: - omx_component_library_Setup; - - # Workaround for an LLVM warning with -simplifycfg-sink-common - # due to LLVM being initialized multiple times. - radeon_drm_winsys_create; - amdgpu_winsys_create; - local: - *; -}; diff --git a/src/gallium/targets/omx/target.c b/src/gallium/targets/omx/target.c deleted file mode 100644 index 308e23bb4a0..00000000000 --- a/src/gallium/targets/omx/target.c +++ /dev/null @@ -1,2 +0,0 @@ -#include "target-helpers/drm_helper.h" -#include "target-helpers/sw_helper.h"