diff --git a/Makefile.am b/Makefile.am index cbcde1a23c..53b75e52c0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -117,7 +117,8 @@ CRUFT_DIRS = \ $(top_srcdir)/ext/swfdec \ $(top_srcdir)/ext/tarkin \ $(top_srcdir)/ext/theora \ - $(top_srcdir)/ext/vp8 + $(top_srcdir)/ext/vp8 \ + $(top_srcdir)/sys/mfc include $(top_srcdir)/common/cruft.mak diff --git a/configure.ac b/configure.ac index 99a97d62e4..9693882ebb 100644 --- a/configure.ac +++ b/configure.ac @@ -1691,55 +1691,6 @@ AG_GST_CHECK_FEATURE(SHM, [POSIX shared memory source and sink], shm, [ fi ]) -dnl *** Video 4 Linux 2 *** -dnl for information about the header/define, see sys/v4l2/gstv4l2element.h -dnl renamed to GST_V4L2 because of some conflict with kernel headers -translit(dnm, m, l) AM_CONDITIONAL(USE_MFC, true) -AG_GST_CHECK_FEATURE(MFC, [Multi Format Codec], mfc, [ - AC_MSG_CHECKING([Checking for up to date v4l2 installation]) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include -#ifdef __sun /* Solaris */ -#include -#include -#elif __FreeBSD__ -#include -#else /* Linux */ -#include -#define _LINUX_TIME_H -#define __user -#include -#endif -#if defined(V4L2_MAJOR_VERSION) || defined(V4L2_MINOR_VERSION) -#error too early v4l2 version or no v4l2 at all -#endif -#if !defined(V4L2_PIX_FMT_H264) -#error v4l2 version too old -#endif - ]], [[ -return 0; - ]])],[ - HAVE_MFC="yes" - AC_MSG_RESULT(yes) - ],[ - HAVE_MFC="no" - AC_MSG_RESULT(no) - - HAVE_VIDEODEV=no - AC_CHECK_HEADER(linux/videodev2.h, [ HAVE_VIDEODEV=yes ], - [ - AC_CHECK_HEADER(sys/videodev2.h, [ HAVE_VIDEODEV=yes ]) - ]) - - if test "x$HAVE_VIDEODEV" = "xyes"; then - AC_MSG_WARN([video4linux2 headers were found, but they're old.]) - AC_MSG_WARN([Please update v4l2 to compile the MFC plugins]) - else - AC_MSG_WARN([v4l2 was not found]) - fi - ]) -]) - dnl check for Video CD translit(dnm, m, l) AM_CONDITIONAL(USE_VCD, true) AG_GST_CHECK_FEATURE(VCD, [Video CD], vcdsrc, [ @@ -3222,7 +3173,6 @@ sys/linsys/Makefile sys/opensles/Makefile sys/osxvideo/Makefile sys/qtwrapper/Makefile -sys/mfc/Makefile sys/shm/Makefile sys/uvch264/Makefile sys/vcd/Makefile diff --git a/sys/Makefile.am b/sys/Makefile.am index 911e55233b..28528be4cd 100644 --- a/sys/Makefile.am +++ b/sys/Makefile.am @@ -160,15 +160,9 @@ else UVCH264_DIR= endif -if USE_MFC -MFC_DIR=mfc -else -MFC_DIR= -endif - -SUBDIRS = $(ACM_DIR) $(ANDROID_MEDIA_DIR) $(APPLE_MEDIA_DIR) $(AVC_DIR) $(BLUEZ_DIR) $(D3DVIDEOSINK_DIR) $(DECKLINK_DIR) $(DIRECTDRAW_DIR) $(DIRECTSOUND_DIR) $(WINKS_DIR) $(DVB_DIR) $(FBDEV_DIR) $(LINSYS_DIR) $(OPENSLES_DIR) $(OSX_VIDEO_DIR) $(PVR_DIR) $(QT_DIR) $(SHM_DIR) $(UVCH264_DIR) $(VCD_DIR) $(VDPAU_DIR) $(WININET_DIR) $(WINSCREENCAP_DIR) $(WASAPI_DIR) $(MFC_DIR) +SUBDIRS = $(ACM_DIR) $(ANDROID_MEDIA_DIR) $(APPLE_MEDIA_DIR) $(AVC_DIR) $(BLUEZ_DIR) $(D3DVIDEOSINK_DIR) $(DECKLINK_DIR) $(DIRECTDRAW_DIR) $(DIRECTSOUND_DIR) $(WINKS_DIR) $(DVB_DIR) $(FBDEV_DIR) $(LINSYS_DIR) $(OPENSLES_DIR) $(OSX_VIDEO_DIR) $(PVR_DIR) $(QT_DIR) $(SHM_DIR) $(UVCH264_DIR) $(VCD_DIR) $(VDPAU_DIR) $(WININET_DIR) $(WINSCREENCAP_DIR) $(WASAPI_DIR) DIST_SUBDIRS = acmenc acmmp3dec androidmedia applemedia applemedia-nonpublic avc bluez d3dvideosink decklink directdraw directsound dvb linsys fbdev dshowdecwrapper dshowsrcwrapper dshowvideosink \ - opensles osxvideo pvr2d qtwrapper shm uvch264 vcd vdpau wasapi wininet winks winscreencap mfc + opensles osxvideo pvr2d qtwrapper shm uvch264 vcd vdpau wasapi wininet winks winscreencap include $(top_srcdir)/common/parallel-subdirs.mak diff --git a/sys/mfc/Makefile.am b/sys/mfc/Makefile.am deleted file mode 100644 index 425e4416d2..0000000000 --- a/sys/mfc/Makefile.am +++ /dev/null @@ -1,26 +0,0 @@ -plugin_LTLIBRARIES = libgstmfc.la - -libgstmfc_la_SOURCES = \ - mfc_decoder/mfc_decoder.c \ - fimc/fimc.c \ - gstmfc.c \ - gstmfcdec.c - -noinst_HEADERS = \ - mfc_decoder/mfc_decoder.h \ - fimc/fimc.h \ - gstmfcdec.h - -libgstmfc_la_CFLAGS = \ - $(GST_PLUGINS_BASE_CFLAGS) \ - $(GST_BASE_CFLAGS) \ - $(GST_CFLAGS) \ - -I$(srcdir) -libgstmfc_la_LIBADD = \ - $(GST_PLUGINS_BASE_LIBS) \ - -lgstvideo-@GST_API_VERSION@ \ - $(GST_BASE_LIBS) \ - $(GST_LIBS) -libgstmfc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstmfc_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS) - diff --git a/sys/mfc/fimc/fimc.c b/sys/mfc/fimc/fimc.c deleted file mode 100644 index 64df868a7c..0000000000 --- a/sys/mfc/fimc/fimc.c +++ /dev/null @@ -1,664 +0,0 @@ -/* - * Copyright (c) 2012 Collabora Ltd. - * Author: Sebastian Dröge - * - * This library is licensed under 2 different licenses and you - * can choose to use it under the terms of any one of them. The - * two licenses are the Apache License 2.0 and the LGPL. - * - * Apache License 2.0: - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * LGPL: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* for g_atomic_* */ -#include - -/* For logging */ -#include -GST_DEBUG_CATEGORY (fimc_debug); -#define GST_CAT_DEFAULT fimc_debug - -#include "fimc.h" - -struct _Fimc -{ - int fd; - - struct v4l2_capability caps; - - int set_src; - int has_src_buffers; - int streamon_src; - FimcColorFormat src_format; - struct v4l2_format src_fmt; - struct v4l2_crop src_crop; - struct v4l2_requestbuffers src_requestbuffers; - - int set_dst; - int has_dst_buffers; - int streamon_dst; - FimcColorFormat dst_format; - struct v4l2_format dst_fmt; - struct v4l2_crop dst_crop; - struct v4l2_requestbuffers dst_requestbuffers; - - struct v4l2_plane dst_planes[3]; - struct v4l2_buffer dst_buffer; - void *dst_buffer_data[3]; - int dst_buffer_size[3]; -}; - -#define FIMC_PATH "/dev/video4" - -static volatile int fimc_in_use; - -void -fimc_init_debug (void) -{ - GST_DEBUG_CATEGORY_INIT (fimc_debug, "fimc", 0, "FIMC library"); -} - -Fimc * -fimc_new (void) -{ - Fimc *fimc; - - if (!g_atomic_int_compare_and_exchange (&fimc_in_use, FALSE, TRUE)) { - GST_ERROR ("Rejected because FIMC is already in use"); - return NULL; - } - - fimc = calloc (1, sizeof (Fimc)); - - fimc->fd = open (FIMC_PATH, O_RDWR, 0); - if (fimc->fd == -1) { - GST_ERROR ("Unable to open FIMC device node: %d", errno); - fimc_free (fimc); - return NULL; - } - - /* check capabilities */ - - if (ioctl (fimc->fd, VIDIOC_QUERYCAP, &fimc->caps) < 0) { - GST_ERROR ("Unable to query capabilities: %d", errno); - fimc_free (fimc); - return NULL; - } - - if ((fimc->caps.capabilities & V4L2_CAP_STREAMING) == 0 || - (fimc->caps.capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE) == 0 || - (fimc->caps.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE) == 0) { - GST_ERROR ("Required capabilities not available"); - fimc_free (fimc); - return NULL; - } - - GST_DEBUG ("Created new FIMC context"); - - return fimc; -} - -void -fimc_free (Fimc * fimc) -{ - fimc_release_src_buffers (fimc); - fimc_release_dst_buffers (fimc); - - if (fimc->fd != -1) - close (fimc->fd); - - g_atomic_int_set (&fimc_in_use, FALSE); - free (fimc); -} - -static int -fimc_color_format_to_v4l2 (FimcColorFormat format) -{ - switch (format) { - case FIMC_COLOR_FORMAT_YUV420SPT: - return V4L2_PIX_FMT_NV12MT; - case FIMC_COLOR_FORMAT_YUV420SP: - return V4L2_PIX_FMT_NV12M; - case FIMC_COLOR_FORMAT_YUV420P: - return V4L2_PIX_FMT_YUV420M; - case FIMC_COLOR_FORMAT_RGB32: - return V4L2_PIX_FMT_RGB32; - default: - break; - } - - return -1; -} - -static int -fimc_color_format_get_nplanes (FimcColorFormat format) -{ - switch (format) { - case FIMC_COLOR_FORMAT_RGB32: - return 1; - case FIMC_COLOR_FORMAT_YUV420SPT: - case FIMC_COLOR_FORMAT_YUV420SP: - return 2; - case FIMC_COLOR_FORMAT_YUV420P: - return 3; - default: - break; - } - - return -1; -} - -static int -fimc_color_format_get_component_height (FimcColorFormat format, int c, - int height) -{ - switch (format) { - case FIMC_COLOR_FORMAT_RGB32: - return height; - case FIMC_COLOR_FORMAT_YUV420SPT: - case FIMC_COLOR_FORMAT_YUV420SP: - case FIMC_COLOR_FORMAT_YUV420P: - if (c == 0) - return height; - else - return (height + 1) / 2; - default: - break; - } - - return -1; -} - -int -fimc_set_src_format (Fimc * fimc, FimcColorFormat format, int width, int height, - int stride[3], int crop_left, int crop_top, int crop_width, int crop_height) -{ - struct v4l2_format fmt; - struct v4l2_crop crop; - struct v4l2_control control; - int i; - - /* Check if something changed */ - if (fimc->set_src && - fimc->src_fmt.fmt.pix_mp.width == width && - fimc->src_fmt.fmt.pix_mp.height == height && - fimc->src_fmt.fmt.pix_mp.pixelformat == fimc_color_format_to_v4l2 (format) - && fimc->src_crop.c.left == crop_left && fimc->src_crop.c.top == crop_top - && fimc->src_crop.c.width == crop_width - && fimc->src_crop.c.height == crop_height) { - if (fimc->src_fmt.fmt.pix_mp.plane_fmt[0].bytesperline == stride[0] && - fimc->src_fmt.fmt.pix_mp.plane_fmt[1].bytesperline == stride[1] && - fimc->src_fmt.fmt.pix_mp.plane_fmt[2].bytesperline == stride[2]) { - GST_DEBUG ("Nothing has changed"); - return 0; - } - } - - /* Something has changed */ - fimc->set_src = 0; - - memset (&fmt, 0, sizeof (fmt)); - memset (&crop, 0, sizeof (crop)); - memset (&control, 0, sizeof (control)); - - fimc->src_format = format; - - fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - fmt.fmt.pix_mp.width = width; - fmt.fmt.pix_mp.height = height; - fmt.fmt.pix_mp.pixelformat = fimc_color_format_to_v4l2 (format); - fmt.fmt.pix_mp.field = V4L2_FIELD_ANY; - fmt.fmt.pix_mp.num_planes = fimc_color_format_get_nplanes (format); - - for (i = 0; i < fmt.fmt.pix_mp.num_planes; i++) { - fmt.fmt.pix_mp.plane_fmt[i].bytesperline = stride[i]; - fmt.fmt.pix_mp.plane_fmt[i].sizeimage = - fimc_color_format_get_component_height (format, i, height) * stride[i]; - } - - if (ioctl (fimc->fd, VIDIOC_S_FMT, &fmt) < 0) { - GST_ERROR ("Failed to set src format: %d", errno); - return -1; - } - - fimc->src_fmt = fmt; - - crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - crop.c.left = crop_left; - crop.c.top = crop_top; - crop.c.width = crop_width; - crop.c.height = crop_height; - - if (ioctl (fimc->fd, VIDIOC_S_CROP, &crop) < 0) { - GST_ERROR ("Failed to set src crop: %d", errno); - return -1; - } - - fimc->src_crop = crop; - - control.id = V4L2_CID_ROTATE; - control.value = 0; - - if (ioctl (fimc->fd, VIDIOC_S_CTRL, &control) < 0) { - GST_ERROR ("Failed to set rotation to 0: %d", errno); - return -1; - } - - fimc->set_src = 1; - - return 0; -} - -int -fimc_request_src_buffers (Fimc * fimc) -{ - struct v4l2_requestbuffers requestbuffers; - - if (fimc->has_dst_buffers) { - GST_ERROR ("Already have dst buffers"); - return -1; - } - - fimc->has_src_buffers = 0; - - memset (&requestbuffers, 0, sizeof (requestbuffers)); - - requestbuffers.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - requestbuffers.memory = V4L2_MEMORY_USERPTR; - requestbuffers.count = 1; - - if (ioctl (fimc->fd, VIDIOC_REQBUFS, &requestbuffers) < 0) { - GST_ERROR ("Failed to request src buffers: %d", errno); - return -1; - } - - fimc->src_requestbuffers = requestbuffers; - - if (requestbuffers.count < 1) { - GST_ERROR ("Got %d buffers instead of %d", requestbuffers.count, 1); - return -1; - } - - fimc->has_src_buffers = 1; - - return 0; -} - -int -fimc_release_src_buffers (Fimc * fimc) -{ - enum v4l2_buf_type type; - - if (fimc->streamon_src) { - type = fimc->src_requestbuffers.type; - if (ioctl (fimc->fd, VIDIOC_STREAMOFF, &type) < 0) { - GST_ERROR ("Deactivating input stream failed: %d", errno); - return -1; - } - fimc->streamon_src = 0; - } - - /* Nothing to do here now */ - fimc->has_src_buffers = 0; - - return 0; -} - -int -fimc_set_dst_format (Fimc * fimc, FimcColorFormat format, int width, int height, - int stride[3], int crop_left, int crop_top, int crop_width, int crop_height) -{ - struct v4l2_format fmt; - struct v4l2_crop crop; - struct v4l2_control control; - int i; - - /* Check if something changed */ - if (fimc->set_dst && - fimc->dst_fmt.fmt.pix_mp.width == width && - fimc->dst_fmt.fmt.pix_mp.height == height && - fimc->dst_fmt.fmt.pix_mp.pixelformat == fimc_color_format_to_v4l2 (format) - && fimc->dst_crop.c.left == crop_left && fimc->dst_crop.c.top == crop_top - && fimc->dst_crop.c.width == crop_width - && fimc->dst_crop.c.height == crop_height) { - if (fimc->dst_fmt.fmt.pix_mp.plane_fmt[0].bytesperline == stride[0] && - fimc->dst_fmt.fmt.pix_mp.plane_fmt[1].bytesperline == stride[1] && - fimc->dst_fmt.fmt.pix_mp.plane_fmt[2].bytesperline == stride[2]) { - GST_DEBUG ("Nothing has changed"); - return 0; - } - } - - /* Something has changed */ - fimc->set_dst = 0; - - memset (&fmt, 0, sizeof (fmt)); - memset (&crop, 0, sizeof (crop)); - memset (&control, 0, sizeof (control)); - - fimc->dst_format = format; - - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - fmt.fmt.pix_mp.width = width; - fmt.fmt.pix_mp.height = height; - fmt.fmt.pix_mp.pixelformat = fimc_color_format_to_v4l2 (format); - fmt.fmt.pix_mp.field = V4L2_FIELD_ANY; - fmt.fmt.pix_mp.num_planes = fimc_color_format_get_nplanes (format); - - for (i = 0; i < fmt.fmt.pix_mp.num_planes; i++) { - fmt.fmt.pix_mp.plane_fmt[i].bytesperline = stride[i]; - fmt.fmt.pix_mp.plane_fmt[i].sizeimage = - fimc_color_format_get_component_height (format, i, height) * stride[i]; - } - - if (ioctl (fimc->fd, VIDIOC_S_FMT, &fmt) < 0) { - GST_ERROR ("Failed to set dst format: %d", errno); - return -1; - } - - fimc->dst_fmt = fmt; - - crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - crop.c.left = crop_left; - crop.c.top = crop_top; - crop.c.width = crop_width; - crop.c.height = crop_height; - - if (ioctl (fimc->fd, VIDIOC_S_CROP, &crop) < 0) { - GST_ERROR ("Failed to set dst crop: %d", errno); - return -1; - } - - fimc->dst_crop = crop; - - control.id = V4L2_CID_ROTATE; - control.value = 0; - - if (ioctl (fimc->fd, VIDIOC_S_CTRL, &control) < 0) { - GST_ERROR ("Failed to set rotation to 0: %d", errno); - return -1; - } - - fimc->set_dst = 1; - - return 0; -} - -int -fimc_request_dst_buffers (Fimc * fimc) -{ - struct v4l2_requestbuffers requestbuffers; - - if (fimc->has_dst_buffers) { - GST_ERROR ("Already have dst buffers"); - return -1; - } - - fimc->has_dst_buffers = 0; - - memset (&requestbuffers, 0, sizeof (requestbuffers)); - - requestbuffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - requestbuffers.memory = V4L2_MEMORY_USERPTR; - requestbuffers.count = 1; - - if (ioctl (fimc->fd, VIDIOC_REQBUFS, &requestbuffers) < 0) { - GST_ERROR ("Failed to request dst buffers: %d", errno); - return -1; - } - - fimc->dst_requestbuffers = requestbuffers; - - if (requestbuffers.count < 1) { - GST_ERROR ("Got %d buffers instead of %d", requestbuffers.count, 1); - return -1; - } - - fimc->has_dst_buffers = 1; - - return 0; -} - -int -fimc_request_dst_buffers_mmap (Fimc * fimc, void *dst[3], int stride[3]) -{ - struct v4l2_requestbuffers requestbuffers; - struct v4l2_plane planes[3]; - struct v4l2_buffer buffer; - int i; - - if (fimc->has_dst_buffers) { - GST_ERROR ("Already have dst buffers"); - return -1; - } - - fimc->has_dst_buffers = 0; - - memset (&requestbuffers, 0, sizeof (requestbuffers)); - memset (planes, 0, sizeof (planes)); - memset (&buffer, 0, sizeof (buffer)); - - requestbuffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - requestbuffers.memory = V4L2_MEMORY_MMAP; - requestbuffers.count = 1; - - if (ioctl (fimc->fd, VIDIOC_REQBUFS, &requestbuffers) < 0) { - GST_ERROR ("Failed to request dst buffers: %d", errno); - return -1; - } - - fimc->dst_requestbuffers = requestbuffers; - - if (requestbuffers.count < 1) { - GST_ERROR ("Got %d buffers instead of %d", requestbuffers.count, 1); - return -1; - } - - buffer.type = fimc->dst_requestbuffers.type; - buffer.memory = fimc->dst_requestbuffers.memory; - buffer.index = 0; - buffer.length = fimc_color_format_get_nplanes (fimc->dst_format); - buffer.m.planes = planes; - - if (ioctl (fimc->fd, VIDIOC_QUERYBUF, &buffer) < 0) { - GST_ERROR ("Query of output buffers failed: %d", errno); - return -1; - } - - fimc->dst_planes[0] = planes[0]; - fimc->dst_planes[1] = planes[1]; - fimc->dst_planes[2] = planes[2]; - fimc->dst_buffer = buffer; - fimc->dst_buffer.m.planes = fimc->dst_planes; - - for (i = 0; i < buffer.length; i++) { - fimc->dst_buffer_data[i] = - mmap (NULL, buffer.m.planes[i].length, PROT_READ | PROT_WRITE, - MAP_SHARED, fimc->fd, buffer.m.planes[i].m.mem_offset); - - if (fimc->dst_buffer_data[i] == MAP_FAILED) { - GST_ERROR ("Failed to map output buffer %d", i); - return -1; - } - fimc->dst_buffer_size[i] = buffer.m.planes[i].length; - - dst[i] = fimc->dst_buffer_data[i]; - stride[i] = fimc->dst_fmt.fmt.pix_mp.plane_fmt[i].bytesperline; - } - - /* FIXME: The device reports wrong strides */ - if (fimc->dst_format == FIMC_COLOR_FORMAT_YUV420P) { - stride[1] /= 2; - stride[2] /= 2; - } - - fimc->has_dst_buffers = 1; - - return 0; -} - -int -fimc_release_dst_buffers (Fimc * fimc) -{ - enum v4l2_buf_type type; - int i; - - if (fimc->streamon_dst) { - type = fimc->dst_requestbuffers.type; - if (ioctl (fimc->fd, VIDIOC_STREAMOFF, &type) < 0) { - GST_ERROR ("Deactivating output stream failed: %d", errno); - return -1; - } - fimc->streamon_dst = 0; - } - - fimc->has_dst_buffers = 0; - - for (i = 0; i < 3; i++) { - if (fimc->dst_buffer_data[i]) - munmap (fimc->dst_buffer_data[i], fimc->dst_buffer_size[i]); - } - - return 0; -} - -int -fimc_convert (Fimc * fimc, void *src[3], void *dst[3]) -{ - struct v4l2_plane planes[3]; - struct v4l2_buffer buffer; - enum v4l2_buf_type type; - int i; - - if (!fimc->set_src || !fimc->set_dst || - !fimc->has_src_buffers || !fimc->has_dst_buffers) { - GST_ERROR ("Not configured yet"); - return -1; - } - - memset (planes, 0, sizeof (planes)); - memset (&buffer, 0, sizeof (buffer)); - - buffer.type = fimc->src_requestbuffers.type; - buffer.memory = fimc->src_requestbuffers.memory; - buffer.length = fimc->src_fmt.fmt.pix_mp.num_planes; - buffer.index = 0; - buffer.m.planes = planes; - - for (i = 0; i < buffer.length; i++) { - buffer.m.planes[i].length = fimc->src_fmt.fmt.pix_mp.plane_fmt[i].sizeimage; - buffer.m.planes[i].m.userptr = (unsigned long) src[i]; - } - - if (ioctl (fimc->fd, VIDIOC_QBUF, &buffer) < 0) { - GST_ERROR ("Failed to queue input buffer: %d", errno); - return -1; - } - - memset (planes, 0, sizeof (planes)); - memset (&buffer, 0, sizeof (buffer)); - - buffer.type = fimc->dst_requestbuffers.type; - buffer.memory = fimc->dst_requestbuffers.memory; - buffer.length = fimc->dst_fmt.fmt.pix_mp.num_planes; - buffer.index = 0; - buffer.m.planes = planes; - - for (i = 0; i < buffer.length; i++) { - buffer.m.planes[i].length = fimc->dst_fmt.fmt.pix_mp.plane_fmt[i].sizeimage; - if (fimc->dst_requestbuffers.memory == V4L2_MEMORY_MMAP) - buffer.m.planes[i].m.mem_offset = fimc->dst_planes[i].m.mem_offset; - else - buffer.m.planes[i].m.userptr = (unsigned long) dst[i]; - } - - if (ioctl (fimc->fd, VIDIOC_QBUF, &buffer) < 0) { - GST_ERROR ("Failed to queue output buffer: %d", errno); - return -1; - } - - if (!fimc->streamon_src) { - type = fimc->src_requestbuffers.type; - if (ioctl (fimc->fd, VIDIOC_STREAMON, &type) < 0) { - GST_ERROR ("Activating input stream failed: %d", errno); - return -1; - } - fimc->streamon_src = 1; - } - - if (!fimc->streamon_dst) { - type = fimc->dst_requestbuffers.type; - if (ioctl (fimc->fd, VIDIOC_STREAMON, &type) < 0) { - GST_ERROR ("Activating output stream failed: %d", errno); - return -1; - } - fimc->streamon_dst = 1; - } - - memset (planes, 0, sizeof (planes)); - memset (&buffer, 0, sizeof (buffer)); - - buffer.type = fimc->src_requestbuffers.type; - buffer.memory = fimc->src_requestbuffers.memory; - buffer.length = fimc->src_fmt.fmt.pix_mp.num_planes; - buffer.m.planes = planes; - - if (ioctl (fimc->fd, VIDIOC_DQBUF, &buffer) < 0) { - GST_ERROR ("Failed to dequeue input buffer: %d", errno); - return -1; - } - - memset (planes, 0, sizeof (planes)); - memset (&buffer, 0, sizeof (buffer)); - - buffer.type = fimc->dst_requestbuffers.type; - buffer.memory = fimc->dst_requestbuffers.memory; - buffer.length = fimc->dst_fmt.fmt.pix_mp.num_planes; - buffer.m.planes = planes; - - if (ioctl (fimc->fd, VIDIOC_DQBUF, &buffer) < 0) { - GST_ERROR ("Failed to dequeue output buffer: %d", errno); - return -1; - } - - return 0; -} diff --git a/sys/mfc/fimc/fimc.h b/sys/mfc/fimc/fimc.h deleted file mode 100644 index f2c34e3c32..0000000000 --- a/sys/mfc/fimc/fimc.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2012 Collabora Ltd. - * Author: Sebastian Dröge - * - * This library is licensed under 2 different licenses and you - * can choose to use it under the terms of any one of them. The - * two licenses are the Apache License 2.0 and the LGPL. - * - * Apache License 2.0: - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * LGPL: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef __FIMC_H__ -#define __FIMC_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct _Fimc Fimc; - -typedef enum { - FIMC_COLOR_FORMAT_YUV420SPT, - FIMC_COLOR_FORMAT_YUV420SP, - FIMC_COLOR_FORMAT_YUV420P, - FIMC_COLOR_FORMAT_RGB32 -} FimcColorFormat; - -void fimc_init_debug (void); - -Fimc * fimc_new (void); -void fimc_free (Fimc * fimc); - -int fimc_set_src_format (Fimc *fimc, FimcColorFormat format, int width, int height, int stride[3], int crop_left, int crop_top, int crop_width, int crop_height); -int fimc_request_src_buffers (Fimc *fimc); -int fimc_release_src_buffers (Fimc *fimc); - -int fimc_set_dst_format (Fimc *fimc, FimcColorFormat format, int width, int height, int stride[3], int crop_left, int crop_top, int crop_width, int crop_height); -int fimc_request_dst_buffers (Fimc *fimc); -int fimc_request_dst_buffers_mmap (Fimc *fimc, void *dst[3], int stride[3]); -int fimc_release_dst_buffers (Fimc *fimc); - -int fimc_convert (Fimc *fimc, void *src[3], void *dst[3]); - -#ifdef __cplusplus -} -#endif - -#endif /* __FIMC_H__ */ diff --git a/sys/mfc/gstmfc.c b/sys/mfc/gstmfc.c deleted file mode 100644 index 7fb22cee1f..0000000000 --- a/sys/mfc/gstmfc.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2012 Collabora Ltd. - * Author: Sebastian Dröge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include "gstmfcdec.h" - -GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PLUGIN_LOADING); - -static gboolean -plugin_init (GstPlugin * plugin) -{ - struct mfc_dec_context *context; - - /* Just check here once if we can create a MFC context, i.e. - * if the hardware is available */ - mfc_dec_init_debug (); - context = mfc_dec_create (CODEC_TYPE_H264); - if (!context) { - GST_CAT_DEBUG (GST_CAT_PLUGIN_LOADING, - "Failed to initialize MFC decoder context"); - return TRUE; - } - mfc_dec_destroy (context); - - if (!gst_element_register (plugin, "mfcdec", GST_RANK_PRIMARY, - GST_TYPE_MFC_DEC)) - return FALSE; - - return TRUE; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - mfc, - "Samsung Exynos MFC plugin", - plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/sys/mfc/gstmfcdec.c b/sys/mfc/gstmfcdec.c deleted file mode 100644 index 64e281b991..0000000000 --- a/sys/mfc/gstmfcdec.c +++ /dev/null @@ -1,1032 +0,0 @@ -/* - * Copyright (C) 2012 Collabora Ltd. - * Author: Sebastian Dröge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstmfcdec.h" - -#include - -GST_DEBUG_CATEGORY_STATIC (gst_mfc_dec_debug); -#define GST_CAT_DEFAULT gst_mfc_dec_debug - -static gboolean gst_mfc_dec_open (GstVideoDecoder * decoder); -static gboolean gst_mfc_dec_start (GstVideoDecoder * decoder); -static gboolean gst_mfc_dec_stop (GstVideoDecoder * decoder); -static gboolean gst_mfc_dec_set_format (GstVideoDecoder * decoder, - GstVideoCodecState * state); -static gboolean gst_mfc_dec_flush (GstVideoDecoder * decoder); -static GstFlowReturn gst_mfc_dec_finish (GstVideoDecoder * decoder); -static GstFlowReturn gst_mfc_dec_handle_frame (GstVideoDecoder * decoder, - GstVideoCodecFrame * frame); -static gboolean gst_mfc_dec_negotiate (GstVideoDecoder * decoder); -static gboolean gst_mfc_dec_decide_allocation (GstVideoDecoder * decoder, - GstQuery * query); - -/* *INDENT-OFF* */ -static GstStaticPadTemplate gst_mfc_dec_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-h264, " - "profile = (string) {constrained-baseline, baseline, main, high}, " - "parsed = (boolean) true, " - "width = (int) [32, 1920], " - "height = (int) [32, 1080], " - "stream-format = (string) byte-stream, " - "alignment = (string) au; " - "video/mpeg, " - "mpegversion = (int) 4, " - "profile = (string) {simple, advanced-simple}, " - "parsed = (boolean) true, " - "width = (int) [32, 1920], " - "height = (int) [32, 1080], " - "systemstream = (boolean) false; " - "video/x-h263, " - "variant = (string) itu, " - "profile = (string) {0, 1, 2, 3}, " - "parsed = (boolean) true, " - "width = (int) [32, 1920], " - "height = (int) [32, 1080]; " - "video/mpeg, " - "mpegversion = (int) [1, 2], " - "parsed = (boolean) true, " - "width = (int) [32, 1920], " - "height = (int) [32, 1080], " - "systemstream = (boolean) false") - ); - -static GstStaticPadTemplate gst_mfc_dec_src_template = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ NV12, I420, YV12, RGBx }")) - ); -/* *INDENT-ON* */ - -#define parent_class gst_mfc_dec_parent_class -G_DEFINE_TYPE (GstMFCDec, gst_mfc_dec, GST_TYPE_VIDEO_DECODER); - -static void -gst_mfc_dec_class_init (GstMFCDecClass * klass) -{ - GstElementClass *element_class; - GstVideoDecoderClass *video_decoder_class; - - element_class = (GstElementClass *) klass; - video_decoder_class = (GstVideoDecoderClass *) klass; - - mfc_dec_init_debug (); - fimc_init_debug (); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_mfc_dec_src_template)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_mfc_dec_sink_template)); - - gst_element_class_set_static_metadata (element_class, - "Samsung Exynos MFC decoder", - "Codec/Decoder/Video", - "Decode video streams via Samsung Exynos", - "Sebastian Dröge "); - - video_decoder_class->open = GST_DEBUG_FUNCPTR (gst_mfc_dec_open); - video_decoder_class->start = GST_DEBUG_FUNCPTR (gst_mfc_dec_start); - video_decoder_class->stop = GST_DEBUG_FUNCPTR (gst_mfc_dec_stop); - video_decoder_class->finish = GST_DEBUG_FUNCPTR (gst_mfc_dec_finish); - video_decoder_class->flush = GST_DEBUG_FUNCPTR (gst_mfc_dec_flush); - video_decoder_class->set_format = GST_DEBUG_FUNCPTR (gst_mfc_dec_set_format); - video_decoder_class->negotiate = GST_DEBUG_FUNCPTR (gst_mfc_dec_negotiate); - video_decoder_class->decide_allocation = - GST_DEBUG_FUNCPTR (gst_mfc_dec_decide_allocation); - video_decoder_class->handle_frame = - GST_DEBUG_FUNCPTR (gst_mfc_dec_handle_frame); - - GST_DEBUG_CATEGORY_INIT (gst_mfc_dec_debug, "mfcdec", 0, - "Samsung Exynos MFC Decoder"); -} - -static void -gst_mfc_dec_init (GstMFCDec * self) -{ - GstVideoDecoder *decoder = (GstVideoDecoder *) self; - - gst_video_decoder_set_packetized (decoder, TRUE); - gst_video_decoder_set_needs_format (decoder, TRUE); -} - -static gboolean -gst_mfc_dec_open (GstVideoDecoder * decoder) -{ - GstMFCDec *self = GST_MFC_DEC (decoder); - - GST_DEBUG_OBJECT (self, "Opening"); - - /* Just check here once if we can create a MFC context, i.e. - * if the hardware is available - */ - self->context = mfc_dec_create (CODEC_TYPE_H264); - if (!self->context) { - GST_ELEMENT_ERROR (self, LIBRARY, INIT, - ("Failed to initialize MFC decoder context"), (NULL)); - return FALSE; - } - mfc_dec_destroy (self->context); - self->context = NULL; - - return TRUE; -} - -static gboolean -gst_mfc_dec_start (GstVideoDecoder * decoder) -{ - GstMFCDec *self = GST_MFC_DEC (decoder); - - GST_DEBUG_OBJECT (self, "Starting"); - - self->width = 0; - self->height = 0; - self->crop_left = 0; - self->crop_top = 0; - self->crop_width = 0; - self->crop_height = 0; - self->format = GST_VIDEO_FORMAT_UNKNOWN; - self->src_stride[0] = 0; - self->src_stride[1] = 0; - self->src_stride[2] = 0; - self->dst[0] = NULL; - self->dst[1] = NULL; - self->dst[2] = NULL; - self->dst_stride[0] = 0; - self->dst_stride[1] = 0; - self->dst_stride[2] = 0; - self->mmap = TRUE; - - return TRUE; -} - -static gboolean -gst_mfc_dec_stop (GstVideoDecoder * video_decoder) -{ - GstMFCDec *self = GST_MFC_DEC (video_decoder); - - GST_DEBUG_OBJECT (self, "Stopping"); - - gst_buffer_replace (&self->codec_data, NULL); - - if (self->input_state) { - gst_video_codec_state_unref (self->input_state); - self->input_state = NULL; - } - - if (self->context) { - mfc_dec_destroy (self->context); - self->context = NULL; - } - self->initialized = FALSE; - - if (self->fimc) { - fimc_free (self->fimc); - self->fimc = NULL; - } - - GST_DEBUG_OBJECT (self, "Stopped"); - - return TRUE; -} - -static gboolean -gst_mfc_dec_set_format (GstVideoDecoder * decoder, GstVideoCodecState * state) -{ - GstMFCDec *self = GST_MFC_DEC (decoder); - GstStructure *s; - - GST_DEBUG_OBJECT (self, "Setting format: %" GST_PTR_FORMAT, state->caps); - - if (self->input_state - && gst_caps_can_intersect (self->input_state->caps, state->caps)) { - GST_DEBUG_OBJECT (self, "Compatible caps"); - goto done; - } - - s = gst_caps_get_structure (state->caps, 0); - - if (self->context) { - mfc_dec_destroy (self->context); - self->context = NULL; - } - self->initialized = FALSE; - - if (gst_structure_has_name (s, "video/x-h264")) { - self->context = mfc_dec_create (CODEC_TYPE_H264); - if (!self->context) { - GST_ELEMENT_ERROR (self, LIBRARY, INIT, - ("Failed to initialize MFC decoder context"), (NULL)); - return FALSE; - } - } else if (gst_structure_has_name (s, "video/mpeg")) { - gint mpegversion; - - if (!gst_structure_get_int (s, "mpegversion", &mpegversion)) - return FALSE; - if (mpegversion != 1 && mpegversion != 2 && mpegversion != 4) - return FALSE; - - if (mpegversion == 1 || mpegversion == 2) { - self->context = mfc_dec_create (CODEC_TYPE_MPEG2); - } else { - self->context = mfc_dec_create (CODEC_TYPE_MPEG4); - } - - if (!self->context) { - GST_ELEMENT_ERROR (self, LIBRARY, INIT, - ("Failed to initialize MFC decoder context"), (NULL)); - return FALSE; - } - } else if (gst_structure_has_name (s, "video/x-h263")) { - self->context = mfc_dec_create (CODEC_TYPE_H263); - if (!self->context) { - GST_ELEMENT_ERROR (self, LIBRARY, INIT, - ("Failed to initialize MFC decoder context"), (NULL)); - return FALSE; - } - } else { - g_return_val_if_reached (FALSE); - } - - if (mfc_dec_init_input (self->context, 1) < 0) { - GST_ELEMENT_ERROR (self, LIBRARY, INIT, - ("Failed to initialize MFC decoder context input"), (NULL)); - return FALSE; - } - - gst_buffer_replace (&self->codec_data, state->codec_data); - -done: - if (self->input_state) - gst_video_codec_state_unref (self->input_state); - self->input_state = gst_video_codec_state_ref (state); - - return TRUE; -} - -static gboolean -gst_mfc_dec_flush (GstVideoDecoder * decoder) -{ - GstMFCDec *self = GST_MFC_DEC (decoder); - - GST_DEBUG_OBJECT (self, "Flushing"); - if (self->context) - mfc_dec_flush (self->context); - - return TRUE; -} - -static GstFlowReturn -gst_mfc_dec_queue_input (GstMFCDec * self, GstVideoCodecFrame * frame) -{ - GstFlowReturn ret = GST_FLOW_OK; - gint mfc_ret; - GstBuffer *inbuf = NULL; - struct mfc_buffer *mfc_inbuf = NULL; - guint8 *mfc_inbuf_data; - gint mfc_inbuf_max_size, mfc_inbuf_size = 0; - GstMapInfo map; - struct timeval timestamp; - - GST_DEBUG_OBJECT (self, "Dequeueing input"); - - if ((mfc_ret = mfc_dec_dequeue_input (self->context, &mfc_inbuf)) < 0) { - if (mfc_ret == -2) { - GST_DEBUG_OBJECT (self, "Timeout dequeueing input, trying again"); - mfc_ret = mfc_dec_dequeue_input (self->context, &mfc_inbuf); - } - - if (mfc_ret < 0) - goto dequeue_error; - } - - mfc_inbuf_data = (guint8 *) mfc_buffer_get_input_data (mfc_inbuf); - g_assert (mfc_inbuf_data != NULL); - mfc_inbuf_max_size = mfc_buffer_get_input_max_size (mfc_inbuf); - - GST_DEBUG_OBJECT (self, "Have input buffer %p with max size %d", - mfc_inbuf_data, mfc_inbuf_max_size); - - g_assert (mfc_inbuf != NULL); - - if (frame) { - if (self->codec_data) { - inbuf = self->codec_data; - gst_buffer_map (inbuf, &map, GST_MAP_READ); - - if ((gsize) mfc_inbuf_max_size < map.size) - goto too_small_inbuf; - - memcpy (mfc_inbuf_data, map.data, map.size); - mfc_inbuf_size += map.size; - mfc_inbuf_data += map.size; - mfc_inbuf_max_size -= map.size; - - gst_buffer_unmap (inbuf, &map); - gst_buffer_replace (&self->codec_data, NULL); - inbuf = NULL; - } - - inbuf = frame->input_buffer; - gst_buffer_map (inbuf, &map, GST_MAP_READ); - - if ((gsize) mfc_inbuf_max_size < map.size) - goto too_small_inbuf; - - memcpy (mfc_inbuf_data, map.data, map.size); - mfc_inbuf_size += map.size; - mfc_inbuf_data += map.size; - mfc_inbuf_max_size -= map.size; - - mfc_buffer_set_input_size (mfc_inbuf, mfc_inbuf_size); - - gst_buffer_unmap (inbuf, &map); - inbuf = NULL; - - timestamp.tv_usec = 0; - timestamp.tv_sec = frame->system_frame_number; - } else { - GST_DEBUG_OBJECT (self, "Passing EOS input buffer"); - - mfc_buffer_set_input_size (mfc_inbuf, 0); - timestamp.tv_usec = 0; - timestamp.tv_sec = -1; - } - - if ((mfc_ret = - mfc_dec_enqueue_input (self->context, mfc_inbuf, ×tamp)) < 0) - goto enqueue_error; - -done: - return ret; - -dequeue_error: - { - GST_ELEMENT_ERROR (self, LIBRARY, FAILED, - ("Failed to dequeue input buffer"), ("mfc_dec_dequeue_input: %d", - mfc_ret)); - ret = GST_FLOW_ERROR; - goto done; - } - -too_small_inbuf: - { - GST_ELEMENT_ERROR (self, STREAM, FORMAT, ("Too large input frames"), - ("Maximum size %d, got %" G_GSIZE_FORMAT, mfc_inbuf_max_size, - map.size)); - ret = GST_FLOW_ERROR; - gst_buffer_unmap (inbuf, &map); - goto done; - } - -enqueue_error: - { - GST_ELEMENT_ERROR (self, LIBRARY, FAILED, - ("Failed to enqueue input buffer"), ("mfc_dec_enqueue_input: %d", - mfc_ret)); - ret = GST_FLOW_ERROR; - goto done; - } -} - -static gboolean -gst_mfc_dec_create_fimc (GstMFCDec * self, GstVideoCodecState * state) -{ - Fimc *fimc; - FimcColorFormat fimc_format; - - fimc = self->fimc; - if (fimc) { - fimc_free (fimc); - self->fimc = fimc = NULL; - } - - fimc = fimc_new (); - - switch (state->info.finfo->format) { - case GST_VIDEO_FORMAT_RGBx: - fimc_format = FIMC_COLOR_FORMAT_RGB32; - break; - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - fimc_format = FIMC_COLOR_FORMAT_YUV420P; - break; - case GST_VIDEO_FORMAT_NV12: - fimc_format = FIMC_COLOR_FORMAT_YUV420SP; - break; - default: - g_assert_not_reached (); - break; - } - - if (fimc_set_src_format (fimc, FIMC_COLOR_FORMAT_YUV420SPT, self->width, - self->height, self->src_stride, self->crop_left, self->crop_top, - self->crop_width, self->crop_height) < 0) - goto fimc_src_error; - - if (fimc_request_src_buffers (fimc) < 0) - goto fimc_src_requestbuffers_error; - - self->fimc = fimc; - self->dst[0] = NULL; - self->dst[1] = NULL; - self->dst[2] = NULL; - self->dst_stride[0] = 0; - self->dst_stride[1] = 0; - self->dst_stride[2] = 0; - - self->fimc_format = fimc_format; - - return TRUE; - -fimc_src_error: - { - GST_ELEMENT_ERROR (self, LIBRARY, FAILED, - ("Failed to set FIMC source parameters"), (NULL)); - fimc_free (fimc); - return FALSE; - } - -fimc_src_requestbuffers_error: - { - GST_ELEMENT_ERROR (self, LIBRARY, FAILED, - ("Failed to request FIMC source buffers"), (NULL)); - fimc_free (fimc); - return FALSE; - } -} - -static gboolean -gst_mfc_dec_negotiate (GstVideoDecoder * decoder) -{ - GstMFCDec *self = GST_MFC_DEC (decoder); - GstVideoCodecState *state; - GstCaps *allowed_caps; - GstVideoFormat format = GST_VIDEO_FORMAT_NV12; - - allowed_caps = gst_pad_get_allowed_caps (GST_VIDEO_DECODER_SRC_PAD (self)); - allowed_caps = gst_caps_truncate (allowed_caps); - allowed_caps = gst_caps_fixate (allowed_caps); - if (!gst_caps_is_empty (allowed_caps)) { - const gchar *format_str; - GstStructure *s = gst_caps_get_structure (allowed_caps, 0); - - format_str = gst_structure_get_string (s, "format"); - if (format_str) - format = gst_video_format_from_string (format_str); - } - gst_caps_unref (allowed_caps); - - self->format = format; - state = - gst_video_decoder_set_output_state (GST_VIDEO_DECODER (self), - self->format, self->crop_width, self->crop_height, self->input_state); - - gst_video_codec_state_unref (state); - - return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder); -} - -static GstFlowReturn -gst_mfc_dec_fill_outbuf (GstMFCDec * self, GstBuffer * outbuf, - struct mfc_buffer *mfc_outbuf, GstVideoCodecState * state) -{ - GstFlowReturn ret = GST_FLOW_OK; - const guint8 *mfc_outbuf_comps[3] = { NULL, }; - gint i, j, h, w, src_stride, dst_stride; - guint8 *dst_, *src_; - GstVideoFrame vframe; - Fimc *fimc = self->fimc; - gboolean zerocopy, has_cropping; - - memset (&vframe, 0, sizeof (vframe)); - - zerocopy = TRUE; - /* FIXME: Not 100% correct, we need the memory of each - * plane to be contiguous at least */ - if (GST_VIDEO_INFO_N_PLANES (&state->info) > gst_buffer_n_memory (outbuf)) { - zerocopy = FALSE; - } else { - gint n = gst_buffer_n_memory (outbuf); - - for (i = 0; i < n; i++) { - GstMemory *mem = gst_buffer_peek_memory (outbuf, i); - - if (!GST_MEMORY_IS_PHYSICALLY_CONTIGUOUS (mem)) { - zerocopy = FALSE; - break; - } - } - } - - has_cropping = self->has_cropping && (self->width != self->crop_width - || self->height != self->crop_height); - - /* We only do cropping if we do zerocopy and downstream - * supports cropping. For non-zerocopy we can do cropping - * more efficient. - * We can't do cropping ourself with zerocopy because - * FIMC returns EFAULT when queueing the destination - * buffers - */ - if (zerocopy && has_cropping) { - GstVideoCropMeta *crop; - - crop = gst_buffer_add_video_crop_meta (outbuf); - crop->x = self->crop_left; - crop->y = self->crop_top; - crop->width = self->crop_width; - crop->height = self->crop_height; - } - - if (!gst_video_frame_map (&vframe, &state->info, outbuf, GST_MAP_WRITE)) - goto frame_map_error; - - mfc_buffer_get_output_data (mfc_outbuf, (void **) &mfc_outbuf_comps[0], - (void **) &mfc_outbuf_comps[1]); - - if (zerocopy && (has_cropping || (self->width == self->crop_width - && self->height == self->crop_height))) { - void *dst[3]; - - if (self->mmap || !self->fimc) { - if (!gst_mfc_dec_create_fimc (self, state)) - goto fimc_create_error; - - fimc = self->fimc; - - if (self->format == GST_VIDEO_FORMAT_NV12) { - self->dst_stride[0] = GST_ROUND_UP_4 (self->width); - self->dst_stride[1] = GST_ROUND_UP_4 (self->width); - self->dst_stride[2] = 0; - } else { - self->dst_stride[0] = GST_ROUND_UP_4 (self->width); - self->dst_stride[1] = GST_ROUND_UP_4 ((self->width + 1) / 2); - self->dst_stride[2] = GST_ROUND_UP_4 ((self->width + 1) / 2); - } - - if (has_cropping) { - if (fimc_set_dst_format (fimc, self->fimc_format, self->width, - self->height, self->dst_stride, 0, 0, self->width, - self->height) < 0) - goto fimc_dst_error; - } else { - if (fimc_set_dst_format (fimc, self->fimc_format, self->width, - self->height, self->dst_stride, self->crop_left, - self->crop_top, self->crop_width, self->crop_height) < 0) - goto fimc_dst_error; - } - self->mmap = FALSE; - - if (fimc_request_dst_buffers (fimc) < 0) - goto fimc_dst_requestbuffers_error; - - self->dst[0] = NULL; - self->dst[1] = NULL; - self->dst[2] = NULL; - } - - dst[0] = GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0); - dst[1] = GST_VIDEO_FRAME_PLANE_DATA (&vframe, 1); - if (self->format == GST_VIDEO_FORMAT_NV12) - dst[2] = NULL; - else - dst[2] = GST_VIDEO_FRAME_PLANE_DATA (&vframe, 2); - - if (fimc_convert (fimc, (void **) mfc_outbuf_comps, (void **) dst) < 0) - goto fimc_convert_error; - } else { - if (!self->mmap || !self->fimc) { - if (!gst_mfc_dec_create_fimc (self, state)) - goto fimc_create_error; - - self->dst_stride[0] = 0; - self->dst_stride[1] = 0; - self->dst_stride[2] = 0; - self->mmap = TRUE; - fimc = self->fimc; - } - - if (!self->dst[0]) { - if (fimc_set_dst_format (fimc, self->fimc_format, self->width, - self->height, self->dst_stride, self->crop_left, - self->crop_top, self->crop_width, self->crop_height) < 0) - goto fimc_dst_error; - - if (fimc_request_dst_buffers_mmap (fimc, self->dst, self->dst_stride) < 0) - goto fimc_dst_requestbuffers_error; - } - - if (fimc_convert (fimc, (void **) mfc_outbuf_comps, - (void **) self->dst) < 0) - goto fimc_convert_error; - - switch (state->info.finfo->format) { - case GST_VIDEO_FORMAT_RGBx: - dst_ = (guint8 *) GST_VIDEO_FRAME_COMP_DATA (&vframe, 0); - src_ = self->dst[0]; - src_stride = self->dst_stride[0]; - h = GST_VIDEO_FRAME_HEIGHT (&vframe); - w = GST_VIDEO_FRAME_WIDTH (&vframe); - dst_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, 0); - for (i = 0; i < h; i++) { - memcpy (dst_, src_, w); - dst_ += dst_stride; - src_ += src_stride; - } - break; - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - for (j = 0; j < 3; j++) { - dst_ = (guint8 *) GST_VIDEO_FRAME_COMP_DATA (&vframe, j); - src_ = self->dst[j]; - src_stride = self->dst_stride[j]; - h = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, j); - w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, j); - dst_stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, j); - for (i = 0; i < h; i++) { - memcpy (dst_, src_, w); - dst_ += dst_stride; - src_ += src_stride; - } - } - break; - case GST_VIDEO_FORMAT_NV12: - for (j = 0; j < 2; j++) { - dst_ = (guint8 *) GST_VIDEO_FRAME_PLANE_DATA (&vframe, j); - src_ = self->dst[j]; - src_stride = self->dst_stride[j]; - h = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, j); - w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, j) * (j == 0 ? 1 : 2); - dst_stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, j); - for (i = 0; i < h; i++) { - memcpy (dst_, src_, w); - dst_ += dst_stride; - src_ += src_stride; - } - } - break; - default: - g_assert_not_reached (); - break; - } - } - -done: - if (vframe.buffer) - gst_video_frame_unmap (&vframe); - - return ret; - -frame_map_error: - { - GST_ELEMENT_ERROR (self, CORE, FAILED, ("Failed to map output buffer"), - (NULL)); - ret = GST_FLOW_ERROR; - goto done; - } - -fimc_create_error: - { - ret = GST_FLOW_ERROR; - goto done; - } - -fimc_dst_error: - { - GST_ELEMENT_ERROR (self, LIBRARY, FAILED, - ("Failed to set FIMC destination parameters"), (NULL)); - ret = GST_FLOW_ERROR; - goto done; - } - -fimc_dst_requestbuffers_error: - { - GST_ELEMENT_ERROR (self, LIBRARY, FAILED, - ("Failed to request FIMC destination buffers"), (NULL)); - ret = GST_FLOW_ERROR; - goto done; - } - -fimc_convert_error: - { - GST_ELEMENT_ERROR (self, LIBRARY, FAILED, - ("Failed to convert via FIMC"), (NULL)); - ret = GST_FLOW_ERROR; - goto done; - } -} - -static GstFlowReturn -gst_mfc_dec_dequeue_output (GstMFCDec * self) -{ - GstFlowReturn ret = GST_FLOW_OK; - gint mfc_ret; - GstVideoCodecFrame *frame = NULL; - GstBuffer *outbuf = NULL; - struct mfc_buffer *mfc_outbuf = NULL; - gint width, height; - gint crop_left, crop_top, crop_width, crop_height; - gint src_ystride, src_uvstride; - GstVideoCodecState *state = NULL; - gint64 deadline; - struct timeval timestamp; - - if (!self->initialized) { - GST_DEBUG_OBJECT (self, "Initializing decoder"); - if ((mfc_ret = mfc_dec_init_output (self->context, 1)) < 0) - goto initialize_error; - self->initialized = TRUE; - } - - while ((mfc_ret = mfc_dec_output_available (self->context)) > 0) { - GST_DEBUG_OBJECT (self, "Dequeueing output"); - - mfc_dec_get_output_size (self->context, &width, &height); - mfc_dec_get_output_stride (self->context, &src_ystride, &src_uvstride); - mfc_dec_get_crop_size (self->context, &crop_left, &crop_top, &crop_width, - &crop_height); - - GST_DEBUG_OBJECT (self, "Have output: width %d, height %d, " - "Y stride %d, UV stride %d, " - "crop_left %d, crop_right %d, " - "crop_width %d, crop_height %d", width, height, src_ystride, - src_uvstride, crop_left, crop_top, crop_width, crop_height); - - state = gst_video_decoder_get_output_state (GST_VIDEO_DECODER (self)); - - if (!state || self->width != width || self->height != height || - self->src_stride[0] != src_ystride - || self->src_stride[1] != src_uvstride - || self->crop_left != crop_left || self->crop_top != crop_top - || self->crop_width != crop_width || self->crop_height != crop_height) { - self->width = width; - self->height = height; - self->crop_left = crop_left; - self->crop_top = crop_top; - self->crop_width = crop_width; - self->crop_height = crop_height; - self->src_stride[0] = src_ystride; - self->src_stride[1] = src_uvstride; - self->src_stride[2] = 0; - - if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (self))) - goto negotiate_error; - - if (state) - gst_video_codec_state_unref (state); - state = gst_video_decoder_get_output_state (GST_VIDEO_DECODER (self)); - } - - if ((mfc_ret = - mfc_dec_dequeue_output (self->context, &mfc_outbuf, - ×tamp)) < 0) { - if (mfc_ret == -2) { - GST_DEBUG_OBJECT (self, "Timeout dequeueing output, trying again"); - mfc_ret = - mfc_dec_dequeue_output (self->context, &mfc_outbuf, ×tamp); - } - - if (mfc_ret < 0) - goto dequeue_error; - } - - g_assert (mfc_outbuf != NULL); - - GST_DEBUG_OBJECT (self, "Got output buffer with ID %ld", timestamp.tv_sec); - - frame = NULL; - if (timestamp.tv_sec != -1) - frame = - gst_video_decoder_get_frame (GST_VIDEO_DECODER (self), - timestamp.tv_sec); - - if (frame) { - deadline = - gst_video_decoder_get_max_decode_time (GST_VIDEO_DECODER (self), - frame); - if (deadline < 0) { - GST_LOG_OBJECT (self, - "Dropping too late frame: deadline %" G_GINT64_FORMAT, deadline); - ret = gst_video_decoder_drop_frame (GST_VIDEO_DECODER (self), frame); - frame = NULL; - outbuf = NULL; - goto done; - } - - ret = - gst_video_decoder_allocate_output_frame (GST_VIDEO_DECODER (self), - frame); - - if (ret != GST_FLOW_OK) - goto alloc_error; - - outbuf = frame->output_buffer; - } else { - GST_WARNING_OBJECT (self, "Didn't find a frame for ID %ld", - timestamp.tv_sec); - - outbuf = - gst_video_decoder_allocate_output_buffer (GST_VIDEO_DECODER (self)); - - if (!outbuf) { - ret = GST_FLOW_ERROR; - goto alloc_error; - } - } - - ret = gst_mfc_dec_fill_outbuf (self, outbuf, mfc_outbuf, state); - if (ret != GST_FLOW_OK) - goto fill_error; - - if (frame) { - ret = gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame); - frame = NULL; - outbuf = NULL; - } else { - ret = gst_pad_push (GST_VIDEO_DECODER_SRC_PAD (self), outbuf); - outbuf = NULL; - } - - if (ret != GST_FLOW_OK) - GST_INFO_OBJECT (self, "Pushing frame returned: %s", - gst_flow_get_name (ret)); - - done: - if (mfc_outbuf) { - if ((mfc_ret = mfc_dec_enqueue_output (self->context, mfc_outbuf)) < 0) - goto enqueue_error; - } - - if (!frame && outbuf) - gst_buffer_unref (outbuf); - if (frame) - gst_video_codec_frame_unref (frame); - if (state) - gst_video_codec_state_unref (state); - - frame = NULL; - outbuf = NULL; - - if (ret != GST_FLOW_OK) - break; - } - - return ret; - -initialize_error: - { - GST_ELEMENT_ERROR (self, LIBRARY, INIT, ("Failed to initialize output"), - ("mfc_dec_init: %d", mfc_ret)); - ret = GST_FLOW_ERROR; - goto done; - } - -negotiate_error: - { - GST_ELEMENT_ERROR (self, CORE, NEGOTIATION, ("Failed to negotiate"), - (NULL)); - ret = GST_FLOW_NOT_NEGOTIATED; - goto done; - } - -dequeue_error: - { - GST_ELEMENT_ERROR (self, LIBRARY, FAILED, - ("Failed to dequeue output buffer"), ("mfc_dec_dequeue_output: %d", - mfc_ret)); - ret = GST_FLOW_ERROR; - goto done; - } - -alloc_error: - { - GST_ELEMENT_ERROR (self, CORE, FAILED, ("Failed to allocate output buffer"), - (NULL)); - ret = GST_FLOW_ERROR; - goto done; - } - -fill_error: - { - GST_ELEMENT_ERROR (self, LIBRARY, FAILED, ("Failed to fill output buffer"), - (NULL)); - ret = GST_FLOW_ERROR; - goto done; - } - -enqueue_error: - { - GST_ELEMENT_ERROR (self, LIBRARY, FAILED, - ("Failed to enqueue output buffer"), ("mfc_dec_enqueue_output: %d", - mfc_ret)); - ret = GST_FLOW_ERROR; - goto done; - } -} - -static GstFlowReturn -gst_mfc_dec_finish (GstVideoDecoder * decoder) -{ - GstMFCDec *self = GST_MFC_DEC (decoder); - GstFlowReturn ret; - - GST_DEBUG_OBJECT (self, "Finishing decoding"); - - if ((ret = gst_mfc_dec_queue_input (self, NULL)) != GST_FLOW_OK) - return ret; - - return gst_mfc_dec_dequeue_output (self); -} - -static GstFlowReturn -gst_mfc_dec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame) -{ - GstMFCDec *self = GST_MFC_DEC (decoder); - GstFlowReturn ret = GST_FLOW_OK; - - GST_DEBUG_OBJECT (self, "Handling frame %d", frame->system_frame_number); - - if ((ret = gst_mfc_dec_queue_input (self, frame)) != GST_FLOW_OK) { - gst_video_codec_frame_unref (frame); - return ret; - } - - gst_video_codec_frame_unref (frame); - - return gst_mfc_dec_dequeue_output (self); -} - -static gboolean -gst_mfc_dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query) -{ - GstMFCDec *self = GST_MFC_DEC (decoder); - GstBufferPool *pool; - GstStructure *config; - guint size, min, max; - - if (!GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (decoder, - query)) - return FALSE; - - g_assert (gst_query_get_n_allocation_pools (query) > 0); - gst_query_parse_nth_allocation_pool (query, 0, &pool, &size, &min, &max); - g_assert (pool != NULL); - - self->has_cropping = FALSE; - config = gst_buffer_pool_get_config (pool); - if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL)) { - gst_buffer_pool_config_add_option (config, - GST_BUFFER_POOL_OPTION_VIDEO_META); - self->has_cropping = - gst_query_find_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE, - NULL); - } - - if (self->has_cropping) { - GstVideoInfo info; - GstCaps *caps; - - /* Calculate uncropped size */ - gst_buffer_pool_config_get_params (config, &caps, &size, &min, &max); - gst_video_info_from_caps (&info, caps); - gst_video_info_set_format (&info, self->format, self->width, self->height); - size = MAX (size, info.size); - caps = gst_video_info_to_caps (&info); - gst_buffer_pool_config_set_params (config, caps, size, min, max); - gst_caps_unref (caps); - } - - gst_query_set_nth_allocation_pool (query, 0, pool, size, min, max); - - gst_buffer_pool_set_config (pool, config); - gst_object_unref (pool); - - return TRUE; -} diff --git a/sys/mfc/gstmfcdec.h b/sys/mfc/gstmfcdec.h deleted file mode 100644 index eeba14332c..0000000000 --- a/sys/mfc/gstmfcdec.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2012 Collabora Ltd. - * Author: Sebastian Dröge - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef __GST_MFC_DEC_H__ -#define __GST_MFC_DEC_H__ - -#include -#include -#include -#include -#include - -#include "mfc_decoder/mfc_decoder.h" -#include "fimc/fimc.h" - -G_BEGIN_DECLS - -#define GST_TYPE_MFC_DEC \ - (gst_mfc_dec_get_type()) -#define GST_MFC_DEC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MFC_DEC,GstMFCDec)) -#define GST_MFC_DEC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MFC_DEC,GstMFCDecClass)) -#define GST_IS_MFC_DEC(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MFC_DEC)) -#define GST_IS_MFC_DEC_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MFC_DEC)) - -typedef struct _GstMFCDec GstMFCDec; -typedef struct _GstMFCDecClass GstMFCDecClass; - -struct _GstMFCDec -{ - GstVideoDecoder parent; - - /* < private > */ - GstVideoCodecState *input_state; - struct mfc_dec_context* context; - gboolean initialized; - GstBuffer *codec_data; - - gboolean has_cropping; - - GstVideoFormat format; - FimcColorFormat fimc_format; - Fimc *fimc; - gint width, height; - gint crop_left, crop_top; - gint crop_width, crop_height; - int src_stride[3]; - - void *dst[3]; - int dst_stride[3]; - gboolean mmap; -}; - -struct _GstMFCDecClass -{ - GstVideoDecoderClass parent_class; -}; - -GType gst_mfc_dec_get_type (void); - -G_END_DECLS - -#endif /* __GST_MFC_DEC_H__ */ diff --git a/sys/mfc/mfc_decoder/mfc_decoder.c b/sys/mfc/mfc_decoder/mfc_decoder.c deleted file mode 100644 index 10eaf825fb..0000000000 --- a/sys/mfc/mfc_decoder/mfc_decoder.c +++ /dev/null @@ -1,763 +0,0 @@ -/* - * Copyright (c) 2012 FXI Technologies - * - * This library is licensed under 2 different licenses and you - * can choose to use it under the terms of any one of them. The - * two licenses are the Apache License 2.0 and the LGPL. - * - * Apache License 2.0: - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * LGPL: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/* - * Author: Haavard Kvaalen - */ - -#include "mfc_decoder.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* For logging */ -#include -GST_DEBUG_CATEGORY (mfc_decoder_debug); -#define GST_CAT_DEFAULT mfc_decoder_debug - -#define MAX_DECODER_INPUT_BUFFER_SIZE (1024 * 3072) -#define NUM_INPUT_PLANES 1 -#define NUM_OUTPUT_PLANES 2 -#define MAX_DECODING_TIME 50 -#define MFC_PATH "/dev/video8" - -static int mfc_in_use; - -/* Protects the mfc_in_use variable */ -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - -struct mfc_dec_context { - int fd; - int num_input_buffers; - int num_output_buffers; - struct mfc_buffer *input_buffer; - struct mfc_buffer *output_buffer; - - int input_streamon, output_streamon; - - /* - * Number of decoded frames the MFC needs to have access to to - * decode correctly. - */ - int required_output_buffers; - int has_free_input_buffers; - /* - * Number of frames that have been decoded. We cannot return them - * if this number is less than required_output_buffers. - */ - int output_frames_available; - int input_frames_queued; - /* We have reached end of stream */ - int eos_reached; - struct { - int w; - int h; - } output_size; - struct { - int left; - int top; - int w; - int h; - } crop_size; - int output_stride[NUM_OUTPUT_PLANES]; -}; - -struct mfc_buffer { - struct { - int length; - int bytesused; - void *data; - } plane[2]; - int index; - int state; -}; - - -enum { - BUFFER_FREE, - BUFFER_ENQUEUED, - BUFFER_DEQUEUED, -}; - -static unsigned int to_v4l2_codec(enum mfc_codec_type codec) -{ - switch (codec) { - case CODEC_TYPE_H264: - return V4L2_PIX_FMT_H264; - case CODEC_TYPE_VC1: - return V4L2_PIX_FMT_VC1_ANNEX_G; - case CODEC_TYPE_VC1_RCV: - return V4L2_PIX_FMT_VC1_ANNEX_L; - case CODEC_TYPE_MPEG4: - return V4L2_PIX_FMT_MPEG4; - case CODEC_TYPE_MPEG1: - return V4L2_PIX_FMT_MPEG1; - case CODEC_TYPE_MPEG2: - return V4L2_PIX_FMT_MPEG2; - case CODEC_TYPE_H263: - return V4L2_PIX_FMT_H263; - } - GST_ERROR ("Invalid codec type %d", codec); - return 0; -} - -int mfc_dec_set_codec(struct mfc_dec_context *ctx, enum mfc_codec_type codec) -{ - int ret; - struct v4l2_format fmt = { - .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, - .fmt = { - .pix_mp = { - .num_planes = 1, - .plane_fmt = { - [0] = { - .sizeimage = MAX_DECODER_INPUT_BUFFER_SIZE, - }, - }, - }, - }, - }; - fmt.fmt.pix_mp.pixelformat = to_v4l2_codec(codec); - - ret = ioctl(ctx->fd, VIDIOC_S_FMT, &fmt); - if (ret) - GST_ERROR ("Unable to set input format"); - return ret; -} - -static int request_input_buffers(struct mfc_dec_context *ctx, int num) -{ - struct v4l2_requestbuffers reqbuf = { - .count = num, - .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, - .memory = V4L2_MEMORY_MMAP, - }; - int i; - - ctx->input_buffer = calloc(num, sizeof (struct mfc_buffer)); - if (!ctx->input_buffer) { - GST_ERROR ("Failed to allocate space for input buffer meta data"); - return -1; - } - - if (ioctl(ctx->fd, VIDIOC_REQBUFS, &reqbuf) < 0) { - GST_ERROR ("Unable to request input buffers"); - return -1; - } - ctx->num_input_buffers = reqbuf.count; - GST_INFO ("Requested %d input buffers, got %d", num, reqbuf.count); - for (i = 0; i < num; i++) { - void *ptr; - struct v4l2_plane planes[NUM_INPUT_PLANES] = {{.length = 0}}; - struct v4l2_buffer buffer = { - .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, - .memory = V4L2_MEMORY_MMAP, - .index = i, - .length = NUM_INPUT_PLANES, - .m = { - .planes = planes, - }, - }; - if (ioctl(ctx->fd, VIDIOC_QUERYBUF, &buffer) < 0) { - GST_ERROR ("Query of input buffer failed"); - return -1; - } - ptr = mmap(NULL, buffer.m.planes[0].length, PROT_READ | PROT_WRITE, - MAP_SHARED, ctx->fd, buffer.m.planes[0].m.mem_offset); - if (ptr == MAP_FAILED) { - GST_ERROR ("Failed to map input buffer"); - return -1; - } - ctx->input_buffer[i].plane[0].length = planes[0].length; - ctx->input_buffer[i].plane[0].data = ptr; - ctx->input_buffer[i].index = i; - ctx->input_buffer[i].state = BUFFER_FREE; - } - ctx->has_free_input_buffers = 1; - return 0; -} - -static int request_output_buffers(struct mfc_dec_context *ctx, int num) -{ - struct v4l2_requestbuffers reqbuf = { - .count = num, - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - .memory = V4L2_MEMORY_MMAP, - }; - int i; - - ctx->output_buffer = calloc(num, sizeof (struct mfc_buffer)); - if (!ctx->output_buffer) { - GST_ERROR ("Failed to allocate space for output buffer meta data"); - return -1; - } - - if (ioctl(ctx->fd, VIDIOC_REQBUFS, &reqbuf) < 0) { - GST_ERROR ("Unable to request output buffers"); - return -1; - } - ctx->num_output_buffers = reqbuf.count; - GST_INFO ("Requested %d output buffers, got %d", num, reqbuf.count); - for (i = 0; i < ctx->num_output_buffers; i++) { - int p; - struct v4l2_plane planes[NUM_OUTPUT_PLANES] = {{.length = 0}}; - struct v4l2_buffer buffer = { - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - .memory = V4L2_MEMORY_MMAP, - .index = i, - .length = NUM_OUTPUT_PLANES, - .m = { - .planes = planes, - }, - }; - ctx->output_buffer[i].index = i; - if (ioctl(ctx->fd, VIDIOC_QUERYBUF, &buffer) < 0) { - GST_ERROR ("Query of output buffer failed"); - return -1; - } - for (p = 0; p < NUM_OUTPUT_PLANES; p++) { - void *ptr = mmap(NULL, buffer.m.planes[p].length, - PROT_READ | PROT_WRITE, MAP_SHARED, - ctx->fd, buffer.m.planes[p].m.mem_offset); - if (ptr == MAP_FAILED) { - GST_ERROR ("Failed to map output buffer"); - return -1; - } - ctx->output_buffer[i].plane[p].length = planes[p].length; - ctx->output_buffer[i].plane[p].data = ptr; - } - if (mfc_dec_enqueue_output(ctx, &ctx->output_buffer[i]) < 0) - return -1; - } - return 0; -} - -struct mfc_dec_context* mfc_dec_create(unsigned int codec) -{ - struct mfc_dec_context *ctx; - struct v4l2_capability caps; - struct stat sb; - - pthread_mutex_lock(&mutex); - if (mfc_in_use) { - GST_ERROR ("Rejected because MFC is already in use"); - pthread_mutex_unlock(&mutex); - return NULL; - } - mfc_in_use = 1; - pthread_mutex_unlock(&mutex); - - ctx = calloc(1, sizeof (struct mfc_dec_context)); - if (!ctx) { - GST_ERROR ("Unable to allocate memory for context"); - goto early_error; - } - ctx->output_frames_available = 0; - - if (stat (MFC_PATH, &sb) < 0) { - GST_INFO ("MFC device node doesn't exist, failing quietly"); - free(ctx); - goto early_error; - } - - GST_INFO ("Opening MFC device node at: %s", MFC_PATH); - ctx->fd = open(MFC_PATH, O_RDWR, 0); - if (ctx->fd == -1) { - GST_WARNING ("Unable to open MFC device node: %d", errno); - free(ctx); - goto early_error; - } - - if (ioctl (ctx->fd, VIDIOC_QUERYCAP, &caps) < 0) { - GST_ERROR ("Unable to query capabilities: %d", errno); - mfc_dec_destroy(ctx); - return NULL; - } - - if ((caps.capabilities & V4L2_CAP_STREAMING) == 0 || - (caps.capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE) == 0 || - (caps.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE) == 0) { - GST_ERROR ("Required capabilities not available"); - mfc_dec_destroy(ctx); - return NULL; - } - - if (mfc_dec_set_codec(ctx, codec) < 0) { - mfc_dec_destroy(ctx); - return NULL; - } - return ctx; - -early_error: - pthread_mutex_lock(&mutex); - mfc_in_use = 0; - pthread_mutex_unlock(&mutex); - return NULL; -} - -static int get_output_format(struct mfc_dec_context *ctx) -{ - int i; - struct v4l2_format fmt = { - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - }; - - if (ioctl(ctx->fd, VIDIOC_G_FMT, &fmt) < 0) { - GST_ERROR ("Failed to get output format"); - return -1; - } - - ctx->output_size.w = fmt.fmt.pix_mp.width; - ctx->output_size.h = fmt.fmt.pix_mp.height; - - for (i = 0; i < NUM_OUTPUT_PLANES; i++) - ctx->output_stride[i] = fmt.fmt.pix_mp.plane_fmt[i].bytesperline; - - return 0; -} - -static int get_crop_data(struct mfc_dec_context *ctx) -{ - struct v4l2_crop crop = { - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - }; - if (ioctl(ctx->fd, VIDIOC_G_CROP, &crop) < 0) { - GST_ERROR ("Unable to get crop data"); - return -1; - } - ctx->crop_size.left = crop.c.left; - ctx->crop_size.top = crop.c.top; - ctx->crop_size.w = crop.c.width; - ctx->crop_size.h = crop.c.height; - return 0; -} - -static int get_minimum_output_buffers(struct mfc_dec_context *ctx) -{ - struct v4l2_control ctrl = { - .id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, - }; - if (ioctl(ctx->fd, VIDIOC_G_CTRL, &ctrl) < 0) { - GST_ERROR ("Failed to get number of output buffers required"); - return -1; - } - ctx->required_output_buffers = ctrl.value + 1; - return 0; -} - -static int start_input_stream(struct mfc_dec_context *ctx) -{ - int type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - if (ioctl(ctx->fd, VIDIOC_STREAMON, &type) < 0) { - GST_ERROR ("Unable to start input stream"); - return -1; - } - ctx->input_streamon = 1; - return 0; -} - -static int start_output_stream(struct mfc_dec_context *ctx) -{ - int type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - if (ioctl(ctx->fd, VIDIOC_STREAMON, &type) < 0) { - GST_ERROR ("Unable to start output stream"); - return -1; - } - ctx->output_streamon = 1; - return 0; -} - -int mfc_dec_init_input(struct mfc_dec_context *ctx, int num_input_buffers) -{ - if (request_input_buffers(ctx, num_input_buffers) < 0) - return -1; - - return 0; -} - -int mfc_dec_init_output(struct mfc_dec_context *ctx, int extra_buffers) -{ - if (start_input_stream(ctx) < 0) - return -1; - - if (get_output_format(ctx) || - get_crop_data(ctx) || - get_minimum_output_buffers(ctx)) - return -1; - - if (request_output_buffers(ctx, ctx->required_output_buffers + extra_buffers)) - return -1; - - if (start_output_stream(ctx) < 0) - return -1; - - return 0; -} - -void mfc_dec_get_output_size(struct mfc_dec_context *ctx, int *w, int *h) -{ - *w = ctx->output_size.w; - *h = ctx->output_size.h; -} - -void mfc_dec_get_output_stride(struct mfc_dec_context *ctx, int *ystride, int *uvstride) -{ - *ystride = ctx->output_stride[0]; - *uvstride = ctx->output_stride[1]; -} - -void mfc_dec_get_crop_size(struct mfc_dec_context *ctx, - int *left, int *top, int *w, int *h) -{ - *left = ctx->crop_size.left; - *top = ctx->crop_size.top; - *w = ctx->crop_size.w; - *h = ctx->crop_size.h; -} - -void mfc_dec_destroy(struct mfc_dec_context *ctx) -{ - int i; - int type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - - if (ctx->output_streamon) - if (ioctl(ctx->fd, VIDIOC_STREAMOFF, &type) < 0) - GST_ERROR ("Streamoff failed on output"); - ctx->output_streamon = 0; - - type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - if (ctx->input_streamon) - if (ioctl(ctx->fd, VIDIOC_STREAMOFF, &type) < 0) - GST_ERROR ("Streamoff failed on input"); - ctx->input_streamon = 0; - - for (i = 0; i < ctx->num_input_buffers; i++) { - if (ctx->input_buffer[i].plane[0].data) - munmap(ctx->input_buffer[i].plane[0].data, - ctx->input_buffer[i].plane[0].length); - } - for (i = 0; i < ctx->num_output_buffers; i++) { - int j; - for (j = 0; j < NUM_OUTPUT_PLANES; j++) - if (ctx->output_buffer[i].plane[j].data) - munmap(ctx->output_buffer[i].plane[j].data, - ctx->output_buffer[i].plane[j].length); - } - if (ctx->input_buffer) - free (ctx->input_buffer); - if (ctx->output_buffer) - free (ctx->output_buffer); - - close(ctx->fd); - pthread_mutex_lock(&mutex); - mfc_in_use = 0; - pthread_mutex_unlock(&mutex); - GST_INFO ("MFC device closed"); - free(ctx); -} - -int mfc_dec_enqueue_input(struct mfc_dec_context *ctx, struct mfc_buffer *buffer, struct timeval *timestamp) -{ - struct v4l2_plane planes[NUM_INPUT_PLANES] = { - [0] = { - .bytesused = buffer->plane[0].bytesused, - }, - }; - struct v4l2_buffer qbuf = { - .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, - .memory = V4L2_MEMORY_MMAP, - .index = buffer->index, - .length = NUM_INPUT_PLANES, - .m = { - .planes = planes, - }, - }; - - if (timestamp) - qbuf.timestamp = *timestamp; - - if (ioctl(ctx->fd, VIDIOC_QBUF, &qbuf) < 0) { - GST_ERROR ("Enqueuing of input buffer %d failed; prev state: %d", - buffer->index, buffer->state); - return -1; - } - - ctx->input_frames_queued++; - buffer->state = BUFFER_ENQUEUED; - if (buffer->plane[0].bytesused == 0) - ctx->eos_reached = 1; - return 0; -} - -static int input_dqbuf(struct mfc_dec_context *ctx, struct mfc_buffer **buffer) -{ - struct v4l2_plane planes[NUM_INPUT_PLANES] = {{.length = 0}}; - struct v4l2_buffer qbuf = { - .type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, - .memory = V4L2_MEMORY_MMAP, - .length = NUM_INPUT_PLANES, - .m = { - .planes = planes, - } - }; - struct pollfd fd = { - .fd = ctx->fd, - .events = POLLOUT | POLLERR, - }; - int pollret; - - pollret = poll(&fd, 1, MAX_DECODING_TIME); - if (pollret < 0) { - GST_ERROR ("%s: Poll returned error: %d", __func__, errno); - return -1; - } - if (pollret == 0) { - GST_INFO ("%s: timed out", __func__); - return -2; - } - - if (ioctl(ctx->fd, VIDIOC_DQBUF, &qbuf) < 0) { - GST_ERROR ("Dequeuing failed"); - return -1; - } - ctx->input_buffer[qbuf.index].plane[0].bytesused = 0; - *buffer = &ctx->input_buffer[qbuf.index]; - ctx->output_frames_available++; - ctx->input_frames_queued--; - return 0; -} - -int mfc_dec_dequeue_input(struct mfc_dec_context *ctx, struct mfc_buffer **buffer) -{ - if (ctx->has_free_input_buffers) { - int i; - *buffer = NULL; - for (i = 0; i < ctx->num_input_buffers; i++) { - if (ctx->input_buffer[i].state == BUFFER_FREE) - *buffer = &ctx->input_buffer[i]; - } - if (!*buffer) { - int ret; - ctx->has_free_input_buffers = 0; - if ((ret = input_dqbuf(ctx, buffer)) < 0) - return ret; - } - } else { - int ret = input_dqbuf(ctx, buffer); - if (ret < 0) - return ret; - } - (*buffer)->state = BUFFER_DEQUEUED; - return 0; -} - -static int release_input_buffer(struct mfc_dec_context *ctx) -{ - struct mfc_buffer *buffer; - struct pollfd fd = { - .fd = ctx->fd, - .events = POLLOUT | POLLERR, - }; - int pollret; - - if (ctx->input_frames_queued == 0) { - GST_INFO ("Nothing to release!"); - return -1; - } - - pollret = poll(&fd, 1, MAX_DECODING_TIME); - if (pollret < 0) { - GST_ERROR ("%s: Poll returned error: %d", __func__, errno); - return -1; - } - if (pollret == 0) { - GST_INFO ("%s: timed out", __func__); - return -2; - } - - GST_DEBUG ("releasing frame; frames queued: %d", ctx->input_frames_queued); - input_dqbuf(ctx, &buffer); - buffer->state = BUFFER_FREE; - ctx->has_free_input_buffers = 1; - return 0; -} - -int mfc_dec_enqueue_output(struct mfc_dec_context *ctx, struct mfc_buffer *buffer) -{ - struct v4l2_plane planes[NUM_OUTPUT_PLANES] = {{.length = 0}}; - struct v4l2_buffer qbuf = { - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - .memory = V4L2_MEMORY_MMAP, - .index = buffer->index, - .length = NUM_OUTPUT_PLANES, - .m = { - .planes = planes, - }, - }; - if (ioctl(ctx->fd, VIDIOC_QBUF, &qbuf) < 0) { - GST_ERROR ("Enqueuing of output buffer %d failed; prev state: %d", - buffer->index, buffer->state); - return -1; - } - buffer->state = BUFFER_ENQUEUED; - return 0; -} - -int mfc_dec_dequeue_output(struct mfc_dec_context *ctx, struct mfc_buffer **buffer, struct timeval *timestamp) -{ - int i; - struct v4l2_plane planes[NUM_OUTPUT_PLANES]; - struct v4l2_buffer qbuf = { - .type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - .memory = V4L2_MEMORY_MMAP, - .m = { - .planes = planes, - }, - .length = NUM_OUTPUT_PLANES, - }; - - if (ioctl(ctx->fd, VIDIOC_DQBUF, &qbuf) < 0) { - GST_ERROR ("Dequeuing failed"); - return -1; - } - - for (i = 0; i < NUM_OUTPUT_PLANES; i++) - ctx->output_buffer[qbuf.index].plane[i].bytesused = qbuf.m.planes[i].bytesused; - - *buffer = &(ctx->output_buffer[qbuf.index]); - - if (timestamp) - *timestamp = qbuf.timestamp; - - ctx->output_frames_available--; - return 0; -} - -int mfc_dec_output_available(struct mfc_dec_context *ctx) -{ - if (ctx->eos_reached) { - if (ctx->input_frames_queued > 0 && - ctx->output_frames_available <= ctx->required_output_buffers) { - release_input_buffer(ctx); - } - - return ctx->output_frames_available > 0; - } - return ctx->output_frames_available >= ctx->required_output_buffers; -} - -int mfc_dec_flush(struct mfc_dec_context *ctx) -{ - int type, i; - int force_dequeue_output = 0; - while (ctx->input_frames_queued > 0) { - int status; - struct mfc_buffer *buffer; - /* Make sure there is room for the decode to finish */ - if (mfc_dec_output_available(ctx) || force_dequeue_output) { - if (mfc_dec_dequeue_output(ctx, &buffer, NULL) < 0) - return -1; - if (mfc_dec_enqueue_output(ctx, buffer) < 0) - return -1; - force_dequeue_output = 0; - } - - status = release_input_buffer(ctx); - if (status == -2) - force_dequeue_output = 1; - if (status == -1) - break; - } - - type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - if (ioctl(ctx->fd, VIDIOC_STREAMOFF, &type) < 0) { - GST_ERROR ("Unable to stop output stream"); - return -1; - } - - for (i = 0; i < ctx->num_output_buffers; i++) { - if (ctx->output_buffer[i].state == BUFFER_ENQUEUED) - if (mfc_dec_enqueue_output(ctx, &ctx->output_buffer[i]) < 0) - return -1; - } - - if (start_output_stream(ctx) < 0) - return -1; - - ctx->output_frames_available = 0; - ctx->eos_reached = 0; - - return 0; -} - -void* mfc_buffer_get_input_data(struct mfc_buffer *buffer) -{ - return buffer->plane[0].data; -} - -int mfc_buffer_get_input_max_size(struct mfc_buffer *buffer) -{ - return buffer->plane[0].length; -} - - -void mfc_buffer_set_input_size(struct mfc_buffer *buffer, int size) -{ - buffer->plane[0].bytesused = size; -} - -void mfc_buffer_get_output_data(struct mfc_buffer *buffer, - void **ybuf, void **uvbuf) -{ - *ybuf = buffer->plane[0].data; - *uvbuf = buffer->plane[1].data; -} - -void mfc_dec_init_debug (void) -{ - GST_DEBUG_CATEGORY_INIT (mfc_decoder_debug, "mfc_decoder", 0, "MFC decoder library"); -} diff --git a/sys/mfc/mfc_decoder/mfc_decoder.h b/sys/mfc/mfc_decoder/mfc_decoder.h deleted file mode 100644 index 971c8e5deb..0000000000 --- a/sys/mfc/mfc_decoder/mfc_decoder.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (c) 2012 FXI Technologies - * - * This library is licensed under 2 different licenses and you - * can choose to use it under the terms of any one of them. The - * two licenses are the Apache License 2.0 and the LGPL. - * - * Apache License 2.0: - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * LGPL: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ -/* - * Author: Haavard Kvaalen - */ - -/* - * Interface for decoding of various video formats using the Samsung - * Multi-Format Video Codec (MFC). - */ - -#ifndef VIDEO_EXYNOS4_MFC_V4L2_INCLUDE_MFC_DECODER_H -#define VIDEO_EXYNOS4_MFC_V4L2_INCLUDE_MFC_DECODER_H - -#include - -struct mfc_buffer; -struct mfc_dec_context; - -enum mfc_codec_type { - CODEC_TYPE_H264, - CODEC_TYPE_VC1, /* VC1 advanced profile */ - CODEC_TYPE_VC1_RCV, /* VC1 simple/main profile */ - CODEC_TYPE_MPEG4, - CODEC_TYPE_MPEG1, - CODEC_TYPE_MPEG2, - CODEC_TYPE_H263, -}; - -#ifdef __cplusplus -extern "C" { -#endif - -void mfc_dec_init_debug (void); - -/* - * Open the MFC decoding device node, and allocate input buffers. - * - * Returns a mfc_dec_context. Note that the context can only be used - * for decoding one stream, i.e. mfc_dec_init can only be called once. - * - * Args: - * codec: Codec type (this can later be changed with mfc_set_codec()). - * num_input_buffers: Numbers of input buffers. There is never any - * need to enqueue more than one buffer for correct decoding. - * - * Returns: A new mfc_dec_context if successful, NULL on error. This - * context is needed for most other calls below, and should be - * deallocated with mfc_dec_destroy(). - */ -struct mfc_dec_context* mfc_dec_create(enum mfc_codec_type codec); - -int mfc_dec_init_input(struct mfc_dec_context*, int num_input_buffers); - -/* - * Destroy context created with mfc_dec_create(). - */ -void mfc_dec_destroy(struct mfc_dec_context*); - -/* - * Initialize video decode. Before this function is called, the - * initial input frame (which contains the header) must be enqueued. - * - * This function allocate output buffers. All output buffers will be - * enqueued initially. The actual number of output buffers depend on the - * - * Args: - * extra_buffers: Numbers of output buffers that can be kept - * dequeued at any time. - * - * Returns: Zero for success, negative value on failure. - */ -int mfc_dec_init_output(struct mfc_dec_context*, int extra_buffers); - - -/* - * This function may be called only before mfc_dec_init(). It is only - * necessary to call if the codec type is different from the one - * supplied to mfc_dec_create(). - * - * Args: - * codec: Codec type - * - * Returns: Zero for success, negative value on failure. - */ -int mfc_dec_set_codec(struct mfc_dec_context*, enum mfc_codec_type codec); - - -/* - * Get size of image output from the MFC. The data might be larger - * than the actual video because of MFC alignment requirements (see - * the crop size below). This function can only be called after - * mfc_dec_init() has been called. - * - * Args: - * w: Width (output). - * h: Height (output). - * - * Returns: Zero for success, negative value on failure. - */ -void mfc_dec_get_output_size(struct mfc_dec_context*, int *w, int *h); -void mfc_dec_get_output_stride(struct mfc_dec_context*, int *ystride, int *uvstride); -void mfc_dec_get_crop_size(struct mfc_dec_context*, - int *left, int *top, int *w, int *h); - -/* - * Check if there are output frames that can be dequeued. - * - * Returns: Positive value if a frame is available, zero if not. - */ -int mfc_dec_output_available(struct mfc_dec_context*); - -/* - * This module use 'input' and 'output' for input to, and output from - * the MFC. The VFL2 names for these interfaces are OUTPUT (for the - * input) and CAPTURE (for the output). - * - * These functions return zero for success, negative value on failure. - * - * When the end of stream has been reached, an empty input frame - * should be enqueued after the last valid input frame. This signal - * to the MFC that EOS has been reached. After this no more input - * frames can be enqueued. - */ - -/* Enqueue frame containing compressed data */ -int mfc_dec_enqueue_input(struct mfc_dec_context*, struct mfc_buffer *buffer, struct timeval *timestamp); -/* - * Dequeue a processed input frame. Will block until one is available. - * - * Returns 0 on success, -1 on failure, and -2 on timeout. A timeout - * typically happens if there are no free output buffers available. - */ -int mfc_dec_dequeue_input(struct mfc_dec_context*, struct mfc_buffer **buffer); -/* Enqueue empty output frame */ -int mfc_dec_enqueue_output(struct mfc_dec_context*, struct mfc_buffer *buffer); -/* - * Dequeue output frame with image data. This should only be called - * when mfc_dec_output_available() returns true. If this is called - * when mfc_dec_output_available() is not true, subsequent video - * frames may not decode correctly. - */ -int mfc_dec_dequeue_output(struct mfc_dec_context*, struct mfc_buffer **buffer, struct timeval *timestamp); - - -/* - * Flush (discard) all enqueued output and input frames. This is - * typically used if we want to seek. - * - * Calling flush resets the "end of stream" state that is entered by - * enqueuing an empty input frame. Thus it is safe to seek at the end - * of the stream as long as mfc_dec_flush() is called first. - */ -int mfc_dec_flush(struct mfc_dec_context*); - -/* - * Get pointer to the input data in 'buffer'. - */ -void* mfc_buffer_get_input_data(struct mfc_buffer *buffer); - -/* - * Get maximum size of input buffer 'buffer' in bytes. - */ -int mfc_buffer_get_input_max_size(struct mfc_buffer *buffer); - -/* - * Set size of data that has been put into 'buffer' in bytes. - */ -void mfc_buffer_set_input_size(struct mfc_buffer *buffer, int size); - -/* - * Get pointers to data in output buffer 'buffer'. - */ -void mfc_buffer_get_output_data(struct mfc_buffer *buffer, - void **ybuf, void **uvbuf); - -#ifdef __cplusplus -} -#endif - - -#endif /* VIDEO_EXYNOS4_MFC_V4L2_INCLUDE_MFC_DECODER_H */