Commit bcec439b authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Video chroma conversions using OpenMAX DL v1.0.2 IP CS(*)

* Development layer / Image processing / Color space conversion

CFLAGS and LIBS must be tweaked manually to use this.
parent 09e8c21d
......@@ -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
/*****************************************************************************
* 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment