[vlc-devel] [PATCH 1/1] Add support for top-bottom anaglyph 3D
Marvin Scholz
epirat07 at gmail.com
Wed Dec 23 19:34:45 UTC 2020
On 22 Dec 2020, at 7:13, amindfv via vlc-devel wrote:
> ---
> modules/video_filter/anaglyph.c | 170
> +++++++++++++++++++++++++++++++-
> 1 file changed, 167 insertions(+), 3 deletions(-)
>
> diff --git a/modules/video_filter/anaglyph.c
> b/modules/video_filter/anaglyph.c
> index b29dfda528..98abbcaa2f 100644
> --- a/modules/video_filter/anaglyph.c
> +++ b/modules/video_filter/anaglyph.c
> @@ -4,6 +4,7 @@
> * Copyright (C) 2000-2012 VLC authors and VideoLAN
> *
> * Authors: Antoine Cellerier <dionoea .t videolan d at t org>
> + * Tom Murphy <amindfv .t mailbox d at t org>
> *
> * 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
> @@ -32,9 +33,12 @@
>
> static int Create(filter_t *);
> static void combine_side_by_side_yuv420(picture_t *, picture_t *,
> int, int);
> +static void combine_top_bottom_yuv420(picture_t *, picture_t *, int,
> int);
>
> #define SCHEME_TEXT N_("Color scheme")
> #define SCHEME_LONGTEXT N_("Define the glasses' color scheme")
> +#define ORIENTATION_TEXT N_("Orientation")
> +#define ORIENTATION_LONGTEXT N_("Orientation of the video's two
> images")
>
> #define FILTER_PREFIX "anaglyph-"
>
> @@ -49,6 +53,12 @@ enum scheme_e
> magenta_cyan,
> };
>
> +enum orientation_e
> +{
> + side_by_side = 1,
> + top_bottom,
> +};
> +
> static const char *const ppsz_scheme_values[] = {
> "red-green",
> "red-blue",
> @@ -64,6 +74,15 @@ static const char *const ppsz_scheme_descriptions[]
> = {
> "magenta (left) cyan (right)",
> };
>
> +static const char *const orientation_values[] = {
> + "side-by-side",
> + "top-bottom",
> + };
> +static const char *const orientation_descriptions[] = {
> + "side-by-side",
> + "top-bottom",
> + };
> +
> vlc_module_begin()
> set_description(N_("Convert 3D picture to anaglyph image video
> filter"));
> set_shortname(N_("Anaglyph"))
> @@ -71,16 +90,19 @@ vlc_module_begin()
> set_subcategory(SUBCAT_VIDEO_VFILTER)
> add_string(FILTER_PREFIX "scheme", "red-cyan", SCHEME_TEXT,
> SCHEME_LONGTEXT, false)
> change_string_list(ppsz_scheme_values,
> ppsz_scheme_descriptions)
> + add_string(FILTER_PREFIX "orientation", "side-by-side",
> ORIENTATION_TEXT, ORIENTATION_LONGTEXT, false)
> + change_string_list(orientation_values,
> orientation_descriptions)
> set_callback_video_filter(Create)
> vlc_module_end()
>
> static const char *const ppsz_filter_options[] = {
> - "scheme", NULL
> + "scheme", "orientation", NULL
> };
>
> typedef struct
> {
> int left, right;
> + enum orientation_e orientation;
> } filter_sys_t;
>
> VIDEO_FILTER_WRAPPER(Filter)
> @@ -100,6 +122,8 @@ static int Create(filter_t *p_filter)
> return VLC_EGENERIC;
> }
>
> +
> +
> p_filter->p_sys = vlc_obj_malloc(VLC_OBJECT(p_filter),
> sizeof(filter_sys_t));
> if (unlikely(!p_filter->p_sys))
> return VLC_ENOMEM;
> @@ -152,6 +176,23 @@ static int Create(filter_t *p_filter)
> break;
> }
>
> + char *orientation_choice = var_CreateGetStringCommand(p_filter,
> +
> FILTER_PREFIX "orientation");
> + p_sys->orientation = side_by_side;
> + if (orientation_choice)
> + {
> + if (!strcmp(orientation_choice, "side-by-side"))
> + p_sys->orientation = side_by_side;
> + else if (!strcmp(orientation_choice, "top-bottom"))
> + p_sys->orientation = top_bottom;
> + else
> + msg_Err(p_filter, "Unknown anaglyph orientation '%s'",
> orientation_choice);
> + }
> + free(orientation_choice);
> +
> +
> +
> +
> p_filter->ops = &Filter_ops;
> return VLC_SUCCESS;
> }
> @@ -165,8 +206,23 @@ static void Filter(filter_t *p_filter, picture_t
> *p_pic, picture_t *p_outpic)
> case VLC_CODEC_I420:
> case VLC_CODEC_J420:
> case VLC_CODEC_YV12:
> - combine_side_by_side_yuv420(p_pic, p_outpic,
> - p_sys->left, p_sys->right);
> + switch (p_sys->orientation)
> + {
> + case side_by_side:
> + combine_side_by_side_yuv420(p_pic, p_outpic,
> + p_sys->left,
> p_sys->right);
> + break;
> + case top_bottom:
> + combine_top_bottom_yuv420(p_pic, p_outpic,
> + p_sys->left,
> p_sys->right);
> + break;
> + default:
> + msg_Warn(p_filter, "Unsupported orientation
> (%4.4s)",
> + (char*)&(p_sys->orientation));
Hi,
it looks like you actually want to log a string but use a format
specifier
usually used to log fourcc's?
> + picture_Release(p_pic);
> + return NULL;
> + }
> +
> break;
>
> default:
> @@ -275,3 +331,111 @@ static void
> combine_side_by_side_yuv420(picture_t *p_inpic, picture_t *p_outpic,
> vout += p_outpic->p[V_PLANE].i_pitch - uv_visible_pitch;
> }
> }
> +
> +static void combine_top_bottom_yuv420(picture_t *p_inpic, picture_t
> *p_outpic,
> + int left, int right)
> +{
> + uint8_t *yino = p_inpic->p[Y_PLANE].p_pixels;
> + uint8_t *uino = p_inpic->p[U_PLANE].p_pixels;
> + uint8_t *vino = p_inpic->p[V_PLANE].p_pixels;
> +
> + uint8_t *yout = p_outpic->p[Y_PLANE].p_pixels;
> + uint8_t *uout = p_outpic->p[U_PLANE].p_pixels;
> + uint8_t *vout = p_outpic->p[V_PLANE].p_pixels;
> +
> + const int in_pitch = p_inpic->p[Y_PLANE].i_pitch;
> +
> + const int y_visible_pitch = p_inpic->p[Y_PLANE].i_visible_pitch;
> + const int y_visible_lines = p_inpic->p[Y_PLANE].i_visible_lines;
> + const int uv_visible_pitch = p_inpic->p[U_PLANE].i_visible_pitch;
> + const int uv_visible_lines = p_inpic->p[U_PLANE].i_visible_lines;
> +
> + const int y_half_size = (y_visible_lines * y_visible_pitch) / 2;
> + const int uv_half_size = (uv_visible_lines * uv_visible_pitch) /
> 2;
> +
> + const uint8_t *yend = yino + y_half_size;
> +
> + int rshift = !!((0xff0000&left) && (0xff0000&right));
> + int gshift = !!((0x00ff00&left) && (0x00ff00&right));
> + int bshift = !!((0x0000ff&left) && (0x0000ff&right));
> +
> + while (yino < yend)
> + {
> + uint8_t *yinu = yino + y_half_size;
> + uint8_t *uinu = uino + uv_half_size;
> + uint8_t *vinu = vino + uv_half_size;
> +
> + const uint8_t *yend = yino + in_pitch;
> +
> + while (yino < yend)
> + {
> + int ro, go, bo, ru, gu, bu, r, g, b;
> +
> + yuv_to_rgb(&ro, &go, &bo, *yino, *uino, *vino);
> + yuv_to_rgb(&ru, &gu, &bu, *yinu, *uinu, *vinu);
> +
> + r = ((!!(0xff0000&left))*ro +
> (!!(0xff0000&right))*ru)>>rshift;
> + g = ((!!(0x00ff00&left))*go +
> (!!(0x00ff00&right))*gu)>>gshift;
> + b = ((!!(0x0000ff&left))*bo +
> (!!(0x0000ff&right))*bu)>>bshift;
> + rgb_to_yuv(yout, uout, vout, r, g, b);
> + // Mirroring a second line below, to make up for the fact
> it's been compresed to half-height:
> + yout[y_visible_pitch] = *yout;
> +
> +
> + yuv_to_rgb(&ro, &go, &bo, *(yino+y_visible_pitch), *uino,
> *vino);
> + yuv_to_rgb(&ru, &gu, &bu, *(yinu+y_visible_pitch), *uinu,
> *vinu);
> +
> + r = ((!!(0xff0000&left))*ro +
> (!!(0xff0000&right))*ru)>>rshift;
> + g = ((!!(0x00ff00&left))*go +
> (!!(0x00ff00&right))*gu)>>gshift;
> + b = ((!!(0x0000ff&left))*bo +
> (!!(0x0000ff&right))*bu)>>bshift;
> +
> + rgb_to_yuv(yout+(y_visible_pitch*2), uout, vout, r, g,
> b);
> + yout[y_visible_pitch*3] = *(yout+(y_visible_pitch*2));
> +
> + yino++;
> + yinu++;
> + yout++;
> +
> +
> + yuv_to_rgb(&ro, &go, &bo, *yino, *uino, *vino);
> + yuv_to_rgb(&ru, &gu, &bu, *yinu, *uinu, *vinu);
> +
> + r = ((!!(0xff0000&left))*ro +
> (!!(0xff0000&right))*ru)>>rshift;
> + g = ((!!(0x00ff00&left))*go +
> (!!(0x00ff00&right))*gu)>>gshift;
> + b = ((!!(0x0000ff&left))*bo +
> (!!(0x0000ff&right))*bu)>>bshift;
> + rgb_to_yuv(yout, uout, vout, r, g, b);
> + yout[y_visible_pitch] = *yout;
> +
> +
> + yuv_to_rgb(&ro, &go, &bo, *(yino+y_visible_pitch), *uino,
> *vino);
> + yuv_to_rgb(&ru, &gu, &bu, *(yinu+y_visible_pitch), *uinu,
> *vinu);
> +
> + r = ((!!(0xff0000&left))*ro +
> (!!(0xff0000&right))*ru)>>rshift;
> + g = ((!!(0x00ff00&left))*go +
> (!!(0x00ff00&right))*gu)>>gshift;
> + b = ((!!(0x0000ff&left))*bo +
> (!!(0x0000ff&right))*bu)>>bshift;
> + rgb_to_yuv(yout+(y_visible_pitch*2),
> uout+uv_visible_pitch, vout+uv_visible_pitch, r, g, b);
> + yout[y_visible_pitch*3] = *(yout+(y_visible_pitch*2));
> +
> + yino++;
> + yinu++;
> + yout++;
> +
> + // There are 1/4 as many U & Y pixels so we write them
> 1/4 as often:
> + uino++;
> + uinu++;
> + uout++;
> + vino++;
> + vinu++;
> + vout++;
> + }
> +
> + // We skip these ins because we looked a row below for the Ys
> already:
> + yino += in_pitch;
> + yinu += in_pitch;
> +
> + yout += y_visible_pitch * 3;
> +
> + uout += uv_visible_pitch;
> + vout += uv_visible_pitch;
> + }
> +}
> --
> 2.20.1
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
More information about the vlc-devel
mailing list