[vlc-devel] [PATCH 2/9] Add transform helper functions.

Matthias Keiser matthias at tristan-inc.com
Wed Mar 5 18:49:17 CET 2014


Am 05.03.2014 um 18:12 schrieb Rémi Denis-Courmont <remi at remlab.net>:

> Le mercredi 5 mars 2014, 17:01:23 Matthias Keiser a écrit :
>> ---
>> include/vlc_es.h     |  48 +++++++++++++
>> src/misc/es_format.c | 196
>> +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 244
>> insertions(+)
>> 
>> diff --git a/include/vlc_es.h b/include/vlc_es.h
>> index 38d63da..d7e43e7 100644
>> --- a/include/vlc_es.h
>> +++ b/include/vlc_es.h
>> @@ -153,6 +153,8 @@ typedef enum video_orientation_t
>>     ORIENT_RIGHT_BOTTOM, /**< Anti-transposed */
>> 
>>     ORIENT_NORMAL      = ORIENT_TOP_LEFT,
>> +    ORIENT_TRANSPOSED  = ORIENT_LEFT_TOP,
>> +    ORIENT_ANTI_TRANSPOSED = ORIENT_RIGHT_BOTTOM,
>>     ORIENT_HFLIPPED    = ORIENT_TOP_RIGHT,
>>     ORIENT_VFLIPPED    = ORIENT_BOTTOM_LEFT,
>>     ORIENT_ROTATED_180 = ORIENT_BOTTOM_RIGHT,
>> @@ -174,6 +176,18 @@ typedef enum video_orientation_t
>> /** Applies horizontal flip to an orientation */
>> #define ORIENT_ROTATE_180(orient) ((orient) ^ 3)
>> 
>> +typedef enum video_transform_t
>> +{
>> +    TRANSFORM_IDENTIY = 0,
>> +    TRANSFORM_HFLIP,
>> +    TRANSFORM_VFLIP,
>> +    TRANSFORM_R90,
>> +    TRANSFORM_R180,
>> +    TRANSFORM_R270,
>> +    TRANSFORM_TRANSPOSE,
>> +    TRANSFORM_ANTI_TRANSPOSE
>> +} video_transform_t;
>> +
> 
> I don't understand why you need a second identical enumeration.

Because it makes sense semantically. It has to do with that we now handle transform from/to arbitrary orientations, as you requested. Conceived example: transforming from ORIENT_VFLIPPED to ORIENT_TRANSPOSED needs a TRANSFORM_R90, it wouldn't make sense to call this ORIENT_ROTATED_90 there. Basically ORIENT_Z = ORIENT_X * TRANSFORM_Y.

>> /**
>>  * video format description
>>  */
>> @@ -265,6 +279,28 @@ VLC_API void video_format_CopyCrop( video_format_t *,
>> const video_format_t * ); VLC_API void video_format_ScaleCropAr(
>> video_format_t *, const video_format_t * );
>> 
>> /**
>> + * This function "normalizes" the formats orientation, by switching the a/r
>> according to the orientation, + * producing a format whose orientation is
>> ORIENT_NORMAL. It makes a shallow copy (pallette is not alloc'ed). + */
>> +VLC_API void video_format_ApplyRotation(const video_format_t * restrict in,
>> video_format_t * restrict out); +
>> +/**
>> + * This function applies the transform operation to fmt.
>> + */
>> +VLC_API void video_format_TransformBy(video_format_t *fmt,
>> video_transform_t transform); +
>> +/**
>> + * This function applies the transforms necessary to fmt so that the
>> resulting fmt + * has the dst_orientation.
>> + */
>> +VLC_API void video_format_TransformTo(video_format_t *fmt,
>> video_orientation_t dst_orientation); +
>> +/**
>> + * Returns the operation required to transform src into dst.
>> + */
>> +VLC_API video_transform_t orientation_GetTransform(video_orientation_t src,
>> video_orientation_t dst);
> 
> Please do not add to the existing shared object prefix namespace pollution.

I'm really sorry but I need more explicit instructions. Would video_format_GetTransform be more acceptable?

>> +
>> +/**
>>  * This function will check if the first video format is similar
>>  * to the second one.
>>  */
>> @@ -275,6 +311,18 @@ VLC_API bool video_format_IsSimilar( const
>> video_format_t *, const video_format_ */
>> VLC_API void video_format_Print( vlc_object_t *, const char *, const
>> video_format_t * );
>> 
>> +
>> +static inline video_transform_t transform_Inverse( video_transform_t
>> transform ) +{
>> +    switch ( transform ) {
>> +        case TRANSFORM_R90:
>> +            return TRANSFORM_R270;
>> +        case TRANSFORM_R270:
>> +            return TRANSFORM_R90;
>> +        default:
>> +            return transform;
>> +    }
>> +}
>> /**
>>  * subtitles format description
>>  */
>> diff --git a/src/misc/es_format.c b/src/misc/es_format.c
>> index 8936414..101974b 100644
>> --- a/src/misc/es_format.c
>> +++ b/src/misc/es_format.c
>> @@ -244,6 +244,202 @@ void video_format_ScaleCropAr( video_format_t *p_dst,
>> const video_format_t *p_sr p_dst->i_sar_num, p_dst->i_sar_den, 65536);
>> }
>> 
>> +//Simplify transforms to have something more managable. Order: angle,
>> hflip. +void transform_GetBasicOps( video_transform_t transform, int
>> *angle, int *hflip ) { +
>> +    *angle = 0;
>> +    *hflip = 0;
>> +
>> +    switch ( transform ) {
>> +
>> +        case TRANSFORM_R90:
>> +            *angle = 90;
>> +            break;
>> +        case TRANSFORM_R180:
>> +            *angle = 180;
>> +            break;
>> +        case TRANSFORM_R270:
>> +            *angle = 270;
>> +            break;
>> +        case TRANSFORM_HFLIP:
>> +            *hflip = 1;
>> +            break;
>> +        case TRANSFORM_VFLIP:
>> +            *angle = 180;
>> +            *hflip = 1;
>> +            break;
>> +        case TRANSFORM_TRANSPOSE:
>> +            *angle = 90;
>> +            *hflip = 1;
>> +            break;
>> +        case TRANSFORM_ANTI_TRANSPOSE:
>> +            *angle = 270;
>> +            *hflip = 1;
>> +            break;
>> +    }
>> +}
>> +
>> +video_transform_t transform_FromBasicOps( int angle, int hflip )
>> +{
>> +    switch ( angle ) {
>> +        case 0:
>> +            return hflip ? TRANSFORM_HFLIP : TRANSFORM_IDENTIY;
>> +        case 90:
>> +            return hflip ? TRANSFORM_TRANSPOSE : TRANSFORM_R90;
>> +        case 180:
>> +            return hflip ? TRANSFORM_VFLIP : TRANSFORM_R180;
>> +        case 270:
>> +            return hflip ? TRANSFORM_ANTI_TRANSPOSE : TRANSFORM_R270;
>> +        default:
>> +            return TRANSFORM_IDENTIY;
>> +    }
>> +}
>> +
>> +video_transform_t orientation_GetNormalTransform( video_orientation_t
>> orient ) +{
>> +    switch( orient ) {
>> +
>> +        case ORIENT_ROTATED_90:
>> +            return TRANSFORM_R90;
>> +        case ORIENT_ROTATED_180:
>> +            return TRANSFORM_R180;
>> +        case ORIENT_ROTATED_270:
>> +            return TRANSFORM_R270;
>> +        case ORIENT_HFLIPPED:
>> +            return TRANSFORM_HFLIP;
>> +        case ORIENT_VFLIPPED:
>> +            return TRANSFORM_VFLIP;
>> +        case ORIENT_TRANSPOSED:
>> +            return TRANSFORM_TRANSPOSE;
>> +        case ORIENT_ANTI_TRANSPOSED:
>> +            return TRANSFORM_ANTI_TRANSPOSE;
>> +        default:
>> +            return TRANSFORM_IDENTIY;
>> +    }
>> +}
>> +
>> +video_transform_t orientation_GetTransform( video_orientation_t src,
>> video_orientation_t dst ) +{
>> +    int angle1 = 0;
>> +    int hflip1 = 0;
>> +
>> +    transform_GetBasicOps( orientation_GetNormalTransform( src ), &angle1,
>> &hflip1 ); +
>> +    int angle2 = 0;
>> +    int hflip2 = 0;
>> +
>> +    transform_GetBasicOps( transform_Inverse(
>> orientation_GetNormalTransform( dst )), &angle2, &hflip2 ); +
>> +    int angle = (angle1 + angle2) % 360;
>> +    int hflip = (hflip1 + hflip2) % 2;
>> +
>> +    return transform_FromBasicOps(angle, hflip);
>> +}
>> +
>> +void video_format_TransformTo( video_format_t *fmt, video_orientation_t
>> dst_orientation ) +{
>> +    video_transform_t transform =
>> orientation_GetTransform(fmt->orientation, dst_orientation); +
>> +    video_format_TransformBy(fmt, transform);
>> +}
>> +
>> +void video_format_TransformBy( video_format_t *fmt, video_transform_t
>> transform ) +{
>> +    /* Get destination orientation */
>> +
>> +    int angle1 = 0;
>> +    int hflip1 = 0;
>> +
>> +    transform_GetBasicOps( transform, &angle1, &hflip1 );
>> +
>> +    int angle2 = 0;
>> +    int hflip2 = 0;
>> +
>> +    transform_GetBasicOps( orientation_GetNormalTransform( fmt->orientation
>> ), &angle2, &hflip2 ); +
>> +    int angle = (angle2 - angle1 + 360) % 360;
>> +    int hflip = (hflip2 - hflip1 + 2) % 2;
>> +
>> +    video_orientation_t dst_orient = ORIENT_NORMAL;
>> +
>> +    if( hflip ) {
>> +
>> +        if( angle == 0 )
>> +            dst_orient = ORIENT_HFLIPPED;
>> +        else if( angle == 90 )
>> +            dst_orient = ORIENT_ANTI_TRANSPOSED;
>> +        else if( angle == 180 )
>> +            dst_orient = ORIENT_VFLIPPED;
>> +        else if( angle == 270 )
>> +            dst_orient = ORIENT_TRANSPOSED;
>> +    }
>> +    else {
>> +
>> +        if( angle == 90 )
>> +            dst_orient = ORIENT_ROTATED_90;
>> +        else if( angle == 180 )
>> +            dst_orient = ORIENT_ROTATED_180;
>> +        else if( angle == 270 )
>> +            dst_orient = ORIENT_ROTATED_270;
>> +    }
>> +
>> +    /* Apply transform */
>> +
>> +    video_format_t scratch = *fmt;
>> +
>> +    if( ORIENT_IS_SWAP( fmt->orientation ) != ORIENT_IS_SWAP( dst_orient ))
>> { +
>> +        fmt->i_width = scratch.i_height;
>> +        fmt->i_visible_width = scratch.i_visible_height;
>> +        fmt->i_height = scratch.i_width;
>> +        fmt->i_visible_height = scratch.i_visible_width;
>> +        fmt->i_sar_num = scratch.i_sar_den;
>> +        fmt->i_sar_den = scratch.i_sar_num;
>> +    }
>> +
>> +    unsigned int delta_y = scratch.i_height - scratch.i_visible_height -
>> scratch.i_y_offset; +    unsigned int delta_x = scratch.i_width -
>> scratch.i_visible_width - scratch.i_x_offset; +
>> +    switch ( transform )
>> +    {
>> +        case TRANSFORM_R90:
>> +            fmt->i_x_offset = delta_y;
>> +            fmt->i_y_offset = scratch.i_x_offset;
>> +            break;
>> +        case TRANSFORM_R180:
>> +            fmt->i_x_offset = delta_x;
>> +            fmt->i_y_offset = delta_y;
>> +            break;
>> +        case TRANSFORM_R270:
>> +            fmt->i_x_offset = scratch.i_y_offset;
>> +            fmt->i_y_offset = delta_x;
>> +            break;
>> +        case TRANSFORM_HFLIP:
>> +            fmt->i_x_offset = delta_x;
>> +            break;
>> +        case TRANSFORM_VFLIP:
>> +            fmt->i_y_offset = delta_y;
>> +            break;
>> +        case TRANSFORM_TRANSPOSE:
>> +            fmt->i_x_offset = scratch.i_y_offset;
>> +            fmt->i_y_offset = scratch.i_x_offset;
>> +            break;
>> +        case TRANSFORM_ANTI_TRANSPOSE:
>> +            fmt->i_x_offset = delta_y;
>> +            fmt->i_y_offset = delta_x;
>> +            break;
>> +    }
>> +
>> +    fmt->orientation = dst_orient;
>> +}
>> +
>> +void video_format_ApplyRotation( const video_format_t * restrict in,
>> video_format_t * restrict out ) +{
>> +    *out = *in;
>> +
>> +    video_format_TransformTo(out, ORIENT_NORMAL);
>> +}
>> +
>> bool video_format_IsSimilar( const video_format_t *p_fmt1, const
>> video_format_t *p_fmt2 ) {
>>     video_format_t v1 = *p_fmt1;
> 
> -- 
> Rémi Denis-Courmont
> http://www.remlab.net/
> 
> _______________________________________________
> 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