]> git.sesse.net Git - vlc/commitdiff
Video chroma conversions using OpenMAX DL v1.0.2 IP CS(*)
authorRémi Denis-Courmont <remi@remlab.net>
Thu, 16 Jun 2011 14:43:20 +0000 (17:43 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Thu, 16 Jun 2011 14:44:42 +0000 (17:44 +0300)
* Development layer / Image processing / Color space conversion

CFLAGS and LIBS must be tweaked manually to use this.

modules/video_chroma/Modules.am
modules/video_chroma/omxdl.c [new file with mode: 0644]

index 32f965fc4b7c621bd836baae075ad542bba2adda..1914edb0070e6d65e8f08060b130f652760fac31 100644 (file)
@@ -41,3 +41,9 @@ libvlc_LTLIBRARIES += \
        libyuy2_i420_plugin.la \
        libyuy2_i422_plugin.la \
        $(NULL)
+
+libchroma_omx_plugin_la_SOURCES = omxdl.c
+libchroma_omx_plugin_la_CFLAGS = $(AM_CFLAGS) $(OMXIP_CFLAGS)
+libchroma_omx_plugin_la_LIBADD = $(AM_LIBADD) $(OMXIP_LIBS)
+libchroma_omx_plugin_la_DEPENDENCIES =
+EXTRA_LTLIBRARIES += libchroma_omx_plugin.la
diff --git a/modules/video_chroma/omxdl.c b/modules/video_chroma/omxdl.c
new file mode 100644 (file)
index 0000000..6c4caf5
--- /dev/null
@@ -0,0 +1,307 @@
+/*****************************************************************************
+ * omxdl.c : OpenMAX DL chroma conversions for VLC
+ *****************************************************************************
+ * Copyright (C) 2011 Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_filter.h>
+#include <omxtypes.h>
+#include <omxIP.h>
+
+static int Open (vlc_object_t *);
+
+vlc_module_begin ()
+    set_description (N_("OpenMAX DL image processing"))
+    set_capability ("video filter2", 90)
+    set_callbacks (Open, NULL)
+vlc_module_end ()
+
+/*** Conversions from I420 ***/
+static void I420_RV16 (filter_t *filter, picture_t *src, picture_t *dst)
+{
+    const OMX_U8 *in[3] = { src->Y_PIXELS, src->U_PIXELS, src->V_PIXELS };
+    OMX_INT instep[3] = { src->Y_PITCH, src->U_PITCH, src->V_PITCH };
+    OMX_U16 *out = (void *)dst->p->p_pixels;
+    OMX_INT outstep = dst->p->i_pitch;
+    OMXSize size = {
+        filter->fmt_in.video.i_width,
+        filter->fmt_in.video.i_height,
+    };
+
+    omxIPCS_YCbCr420ToBGR565_U8_U16_P3C3R (in, instep, out, outstep, size);
+}
+VIDEO_FILTER_WRAPPER (I420_RV16)
+
+/*** Conversions from YV12 ***/
+static void YV12_RV16 (filter_t *filter, picture_t *src, picture_t *dst)
+{
+    const OMX_U8 *in[3] = { src->Y_PIXELS, src->V_PIXELS, src->U_PIXELS };
+    OMX_INT instep[3] = { src->Y_PITCH, src->V_PITCH, src->U_PITCH };
+    OMX_U16 *out = (void *)dst->p->p_pixels;
+    OMX_INT outstep = dst->p->i_pitch;
+    OMXSize size = {
+        filter->fmt_in.video.i_width,
+        filter->fmt_in.video.i_height,
+    };
+
+    omxIPCS_YCbCr420ToBGR565_U8_U16_P3C3R (in, instep, out, outstep, size);
+}
+VIDEO_FILTER_WRAPPER (YV12_RV16)
+
+/*** Conversions from I422 ***/
+static void I422_I420 (filter_t *filter, picture_t *src, picture_t *dst)
+{
+    const OMX_U8 *in[3] = { src->Y_PIXELS, src->U_PIXELS, src->V_PIXELS };
+    OMX_INT instep[3] = { src->Y_PITCH, src->U_PITCH, src->V_PITCH };
+    OMX_U8 *out[3] = { dst->Y_PIXELS, dst->U_PIXELS, dst->V_PIXELS };
+    OMX_INT outstep[3] = { dst->Y_PITCH, dst->U_PITCH, dst->V_PITCH };
+    OMXSize size = {
+        filter->fmt_in.video.i_width,
+        filter->fmt_in.video.i_height,
+    };
+
+    omxIPCS_YCbCr422ToYCbCr420Rotate_U8_P3R (
+        in, instep, out, outstep, size, OMX_IP_DISABLE);
+}
+VIDEO_FILTER_WRAPPER (I422_I420)
+
+static void I422_YV12 (filter_t *filter, picture_t *src, picture_t *dst)
+{
+    const OMX_U8 *in[3] = { src->Y_PIXELS, src->U_PIXELS, src->V_PIXELS };
+    OMX_INT instep[3] = { src->Y_PITCH, src->U_PITCH, src->V_PITCH };
+    OMX_U8 *out[3] = { dst->Y_PIXELS, dst->V_PIXELS, dst->U_PIXELS };
+    OMX_INT outstep[3] = { dst->Y_PITCH, dst->V_PITCH, dst->U_PITCH };
+    OMXSize size = {
+        filter->fmt_in.video.i_width,
+        filter->fmt_in.video.i_height,
+    };
+
+    omxIPCS_YCbCr422ToYCbCr420Rotate_U8_P3R (
+        in, instep, out, outstep, size, OMX_IP_DISABLE);
+}
+VIDEO_FILTER_WRAPPER (I422_YV12)
+
+/*** Conversions from I444 ***/
+static void I444_RV16 (filter_t *filter, picture_t *src, picture_t *dst)
+{
+    const OMX_U8 *in[3] = { src->Y_PIXELS, src->U_PIXELS, src->V_PIXELS };
+    OMX_INT instep = src->p->i_pitch;
+    OMX_U16 *out = (void *)dst->p->p_pixels;
+    OMX_INT outstep = dst->p->i_pitch;
+    OMXSize size = {
+        filter->fmt_in.video.i_width,
+        filter->fmt_in.video.i_height,
+    };
+
+    omxIPCS_YCbCr444ToBGR565_U8_U16_P3C3R (in, instep, out, outstep, size);
+}
+VIDEO_FILTER_WRAPPER (I444_RV16)
+
+/*** Conversions from YUY2 ***/
+static void YUYV_RV24 (filter_t *filter, picture_t *src, picture_t *dst)
+{
+    const OMX_U8 *in = src->p->p_pixels;
+    OMX_INT instep = src->p->i_pitch;
+    OMX_U8 *out = dst->p->p_pixels;
+    OMX_INT outstep = dst->p->i_pitch;
+    OMXSize size = {
+        filter->fmt_in.video.i_width,
+        filter->fmt_in.video.i_height,
+    };
+
+    omxIPCS_YCbYCr422ToBGR888_U8_C2C3R (in, instep, out, outstep, size);
+}
+VIDEO_FILTER_WRAPPER (YUYV_RV24)
+
+static void YUYV_RV16 (filter_t *filter, picture_t *src, picture_t *dst)
+{
+    const OMX_U8 *in = src->p->p_pixels;
+    OMX_INT instep = src->p->i_pitch;
+    OMX_U16 *out = (void *)dst->p->p_pixels;
+    OMX_INT outstep = dst->p->i_pitch;
+    OMXSize size = {
+        filter->fmt_in.video.i_width,
+        filter->fmt_in.video.i_height,
+    };
+
+    omxIPCS_YCbYCr422ToBGR565_U8_U16_C2C3R (in, instep, out, outstep, size);
+}
+VIDEO_FILTER_WRAPPER (YUYV_RV16)
+
+/*** Conversions from UYVY ***/
+static void UYVY_I420 (filter_t *filter, picture_t *src, picture_t *dst)
+{
+    const OMX_U8 *in = src->p->p_pixels;
+    OMX_INT instep = src->p->i_pitch;
+    OMX_U8 *out[3] = { dst->Y_PIXELS, dst->U_PIXELS, dst->V_PIXELS };
+    OMX_INT outstep[3] = { dst->Y_PITCH, dst->U_PITCH, dst->V_PITCH };
+    OMXSize size = {
+        filter->fmt_in.video.i_width,
+        filter->fmt_in.video.i_height,
+    };
+
+    omxIPCS_CbYCrY422ToYCbCr420Rotate_U8_C2P3R (
+        in, instep, out, outstep, size, OMX_IP_DISABLE);
+}
+VIDEO_FILTER_WRAPPER (UYVY_I420)
+
+static void UYVY_YV12 (filter_t *filter, picture_t *src, picture_t *dst)
+{
+    const OMX_U8 *in = src->p->p_pixels;
+    OMX_INT instep = src->p->i_pitch;
+    OMX_U8 *out[3] = { dst->Y_PIXELS, dst->V_PIXELS, dst->U_PIXELS };
+    OMX_INT outstep[3] = { dst->Y_PITCH, dst->V_PITCH, dst->U_PITCH };
+    OMXSize size = {
+        filter->fmt_in.video.i_width,
+        filter->fmt_in.video.i_height,
+    };
+
+    omxIPCS_CbYCrY422ToYCbCr420Rotate_U8_C2P3R (
+        in, instep, out, outstep, size, OMX_IP_DISABLE);
+}
+VIDEO_FILTER_WRAPPER (UYVY_YV12)
+
+/*** Initialization ***/
+static int FixRV24 (video_format_t *fmt)
+{
+#ifndef WORDS_BIGENDIAN
+    if (fmt->i_rmask == 0 && fmt->i_gmask == 0 && fmt->i_bmask == 0)
+    {
+        fmt->i_rmask = 0xff0000;
+        fmt->i_gmask = 0x00ff00;
+        fmt->i_bmask = 0x0000ff;
+    }
+    return (fmt->i_rmask == 0xff0000 && fmt->i_gmask == 0x00ff00
+         && fmt->i_bmask == 0x0000ff) ? 0 : -1;
+#else
+    if (fmt->i_rmask == 0 && fmt->i_gmask == 0 && fmt->i_bmask == 0)
+    {
+        fmt->i_rmask = 0x0000ff;
+        fmt->i_gmask = 0x00ff00;
+        fmt->i_bmask = 0xff0000;
+    }
+    return (fmt->i_rmask == 0x0000ff && fmt->i_gmask == 0x00ff00
+         && fmt->i_bmask == 0xff0000) ? 0 : -1;
+#endif
+}
+static int FixRV16 (video_format_t *fmt)
+{
+#ifndef WORDS_BIGENDIAN
+    if (fmt->i_rmask == 0 && fmt->i_gmask == 0 && fmt->i_bmask == 0)
+    {
+        fmt->i_rmask = 0xf800;
+        fmt->i_gmask = 0x07e0;
+        fmt->i_bmask = 0x001f;
+    }
+    return (fmt->i_rmask == 0xf800 && fmt->i_gmask == 0x07e0
+         && fmt->i_bmask == 0x001f) ? 0 : -1;
+#else
+    return -1;
+#endif
+}
+
+static int Open (vlc_object_t *obj)
+{
+    filter_t *filter = (filter_t *)obj;
+
+    if ((filter->fmt_in.video.i_width != filter->fmt_out.video.i_width)
+     || (filter->fmt_in.video.i_height != filter->fmt_out.video.i_height))
+        return VLC_EGENERIC;
+
+    switch (filter->fmt_in.video.i_chroma)
+    {
+        case VLC_CODEC_I420:
+            switch (filter->fmt_out.video.i_chroma)
+            {
+                case VLC_CODEC_RGB16:
+                    if (FixRV16 (&filter->fmt_out.video))
+                        return VLC_EGENERIC;
+                    filter->pf_video_filter = I420_RV16_Filter;
+                    return VLC_SUCCESS;
+            }
+            break;
+
+        case VLC_CODEC_YV12:
+            switch (filter->fmt_out.video.i_chroma)
+            {
+                case VLC_CODEC_RGB16:
+                    if (FixRV16 (&filter->fmt_out.video))
+                        return VLC_EGENERIC;
+                    filter->pf_video_filter = YV12_RV16_Filter;
+                    return VLC_SUCCESS;
+            }
+            break;
+
+        case VLC_CODEC_I422:
+            switch (filter->fmt_out.video.i_chroma)
+            {
+                case VLC_CODEC_I420:
+                    filter->pf_video_filter = I422_I420_Filter;
+                    return VLC_SUCCESS;
+                case VLC_CODEC_YV12:
+                    filter->pf_video_filter = I422_YV12_Filter;
+                    return VLC_SUCCESS;
+            }
+            break;
+
+        case VLC_CODEC_I444:
+            switch (filter->fmt_out.video.i_chroma)
+            {
+                case VLC_CODEC_RGB16:
+                    if (FixRV16 (&filter->fmt_out.video))
+                        return VLC_EGENERIC;
+                    filter->pf_video_filter = I444_RV16_Filter;
+                    return VLC_SUCCESS;
+            }
+            break;
+
+        case VLC_CODEC_YUYV:
+            switch (filter->fmt_out.video.i_chroma)
+            {
+                case VLC_CODEC_RGB24:
+                    if (FixRV24 (&filter->fmt_out.video))
+                        return VLC_EGENERIC;
+                    filter->pf_video_filter = YUYV_RV24_Filter;
+                    return VLC_SUCCESS;
+                case VLC_CODEC_RGB16:
+                    if (FixRV16 (&filter->fmt_out.video))
+                        return VLC_EGENERIC;
+                    filter->pf_video_filter = YUYV_RV16_Filter;
+                    return VLC_SUCCESS;
+            }
+            break;
+
+        case VLC_CODEC_UYVY:
+            switch (filter->fmt_out.video.i_chroma)
+            {
+                case VLC_CODEC_I420:
+                    filter->pf_video_filter = UYVY_I420_Filter;
+                    return VLC_SUCCESS;
+                case VLC_CODEC_YV12:
+                    filter->pf_video_filter = UYVY_YV12_Filter;
+                    return VLC_SUCCESS;
+            }
+            break;
+    }
+    return VLC_EGENERIC;
+}