[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