[vlc-devel] [PATCH 1/2] Support over-under 3D anaglyphs
amindfv at gmail.com
amindfv at gmail.com
Fri Jan 18 23:15:56 CET 2019
Is there a good reference for how the concept of "visible" works in VLC? I've got code that works but I'd like to be sure I'm doing it right, and I can't find anything in the wiki.
Thanks!
Tom
> El 16 ene 2019, a las 3:25 AM, Steve Lhomme <robux4 at ycbcr.xyz> escribió:
>
>
>
>> On 16/01/2019 04:43, Tom Murphy wrote:
>> ---
>> modules/video_filter/anaglyph.c | 171 +++++++++++++++++++++++++++++++++++++++-
>> 1 file changed, 168 insertions(+), 3 deletions(-)
>>
>> diff --git a/modules/video_filter/anaglyph.c b/modules/video_filter/anaglyph.c
>> index 2bfeafb54d..4ec38fc90a 100644
>> --- a/modules/video_filter/anaglyph.c
>> +++ b/modules/video_filter/anaglyph.c
>> @@ -5,6 +5,7 @@
>> * $Id$
>> *
>> * Authors: Antoine Cellerier <dionoea .t videolan d at t org>
>> + * Tom Murphy <amindfv .t gmail d at t com>
>> *
>> * 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
>> @@ -34,10 +35,14 @@
>> static int Create(vlc_object_t *);
>> static void Destroy(vlc_object_t *);
>> static picture_t *Filter(filter_t *, picture_t *);
>> +
>> static void combine_side_by_side_yuv420(picture_t *, picture_t *, int, int);
>> +static void combine_over_under_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-"
>> @@ -52,6 +57,12 @@ enum scheme_e
>> magenta_cyan,
>> };
>> +enum orientation_e
>> +{
>> + side_by_side = 1,
>> + over_under,
>> +};
>> +
>> static const char *const ppsz_scheme_values[] = {
>> "red-green",
>> "red-blue",
>> @@ -67,6 +78,15 @@ static const char *const ppsz_scheme_descriptions[] = {
>> "magenta (left) cyan (right)",
>> };
>> +static const char *const orientation_values[] = {
>> + "side-by-side",
>> + "over-under",
>> + };
>> +static const char *const orientation_descriptions[] = {
>> + "side-by-side",
>> + "over-under",
>> + };
>> +
>> vlc_module_begin()
>> set_description(N_("Convert 3D picture to anaglyph image video filter"));
>> set_shortname(N_("Anaglyph"))
>> @@ -75,16 +95,20 @@ vlc_module_begin()
>> set_capability("video filter", 0)
>> 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_callbacks(Create, Destroy)
>> 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;
>> @@ -105,6 +129,8 @@ static int Create(vlc_object_t *p_this)
>> return VLC_EGENERIC;
>> }
>> +
>> +
>> p_filter->p_sys = malloc(sizeof(filter_sys_t));
>> if (!p_filter->p_sys)
>> return VLC_ENOMEM;
>> @@ -157,6 +183,20 @@ static int Create(vlc_object_t *p_this)
>> 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, "over-under"))
>> + p_sys->orientation = over_under;
>> + else
>> + msg_Err(p_filter, "Unknown anaglyph orientation '%s'", orientation_choice);
>> + }
>> + free(orientation_choice);
>> +
>> p_filter->pf_video_filter = Filter;
>> return VLC_SUCCESS;
>> }
>> @@ -187,8 +227,22 @@ static picture_t *Filter(filter_t *p_filter, picture_t *p_pic)
>> 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 over_under:
>> + combine_over_under_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));
>> + picture_Release(p_pic);
>> + return NULL;
>> + }
>> break;
>> default:
>> @@ -303,3 +357,114 @@ static void combine_side_by_side_yuv420(picture_t *p_inpic, picture_t *p_outpic,
>> }
>> }
>> +
>> +
>> +
>> +static void combine_over_under_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;
>
> This doesn't seem right. The u plane should probably depend on the full amount of lines, not just the visible ones. Same thing for the v plane.
>
>> + 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.11.0
>>
>> _______________________________________________
>> vlc-devel mailing list
>> To unsubscribe or modify your subscription options:
>> https://mailman.videolan.org/listinfo/vlc-devel
>
> _______________________________________________
> 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